﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Область СлужебныеПроцедурыИФункции

#Область ПечатьВФорматеOfficeOpenXML

Функция СформироватьПечатныеФормы(ТаблицаПечатныхФорм, ПараметрыФормирования, ОфисныеДокументы, СтруктураЕдиногоДокумента) Экспорт
	
	Если ПараметрыФормирования.Количество() Тогда
		
		ТипыОбъектовПечати = Неопределено;
		ДополнительныеПараметры = Новый Структура("ДополнитьКомплектВнешнимиПечатнымиФормами", Ложь);
		СоставЕдиногоДокумента = Новый Соответствие();
		
		Для Каждого СтрокаПечатнойФормы Из ТаблицаПечатныхФорм Цикл
			Если СтрокаПечатнойФормы.ФормироватьЗаново Тогда
				ДополнительныеПараметры.Вставить("ПодписьИПечать", СтрокаПечатнойФормы.ПодписьИПечать);
				МассивОбъектовПечати = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(СтрокаПечатнойФормы.ОбъектПечати);
				ПечатныеФормы = УправлениеПечатью.СформироватьПечатныеФормы("УправлениеПечатью", СтрокаПечатнойФормы.ИмяМакета,
					МассивОбъектовПечати, ДополнительныеПараметры, ТипыОбъектовПечати, СтрокаПечатнойФормы.ТекущийЯзык);
					
				Если ПечатныеФормы.КоллекцияПечатныхФорм.Количество() Тогда
					СтрокаПечатныхФорм = ПечатныеФормы.КоллекцияПечатныхФорм[0];
					Для Каждого ЭлементОфисногоДокумента Из СтрокаПечатныхФорм.ОфисныеДокументы Цикл
						ОфисныйДокумент = ПолучитьИзВременногоХранилища(ЭлементОфисногоДокумента.Ключ);
						ОфисныеДокументы.Вставить(СтрокаПечатнойФормы.АдресПечатнойФормы, ОфисныйДокумент);
						ПоместитьВоВременноеХранилище(ОфисныйДокумент, СтрокаПечатнойФормы.АдресПечатнойФормы);
						Прервать;
					КонецЦикла;
				Иначе
					ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Ошибка: Не удалось сформировать %1'"), СтрокаПечатнойФормы.Представление);
				КонецЕсли;
			КонецЕсли;
			
			Если СтрокаПечатнойФормы.Пометка Тогда
				СвойстваПечатнойФормы = Новый Структура("ПодписьИПечать, ТекущийЯзык");
				СвойстваПечатнойФормы.ПодписьИПечать = СтрокаПечатнойФормы.ПодписьИПечать;
				СвойстваПечатнойФормы.ТекущийЯзык = СтрокаПечатнойФормы.ТекущийЯзык;
				СоставЕдиногоДокумента.Вставить(СтрокаПечатнойФормы.АдресПечатнойФормы, СвойстваПечатнойФормы);
			КонецЕсли;
		КонецЦикла;
		
		
		Если ПараметрыФормирования.Свойство("ПереформироватьЕдиныйДокумент") И ПараметрыФормирования.ПереформироватьЕдиныйДокумент Тогда
			
			ОфисныеДокументыДляОбъединения = Новый Соответствие();
			
			Для Каждого ПечатнаяФорма Из СоставЕдиногоДокумента Цикл
				ОфисныеДокументыДляОбъединения.Вставить(ПечатнаяФорма.Ключ, ОфисныеДокументы[ПечатнаяФорма.Ключ]);
			КонецЦикла;
			
			СтруктураЕдиногоДокумента.Вставить("АдресПечатнойФормы", ОбъединитьОфисныеДокументы(ОфисныеДокументыДляОбъединения, СтруктураЕдиногоДокумента.АдресПечатнойФормы));
			
			Представление = СтрСоединить(ТаблицаПечатныхФорм.ВыгрузитьКолонку("Представление"), ", ");
			Если СтрДлина(Представление) > 50 Тогда
				Представление = Лев(Представление, 50)+"...";
			КонецЕсли;
			
			СтруктураЕдиногоДокумента.Вставить("ИмяФайлаПечатнойФормы", Представление+".docx");
			СтруктураЕдиногоДокумента.Вставить("Представление", Представление);
			СтруктураЕдиногоДокумента.Вставить("СоставЕдиногоДокумента", СоставЕдиногоДокумента);
			
		КонецЕсли;
	КонецЕсли;
	Возврат СтруктураЕдиногоДокумента;		
КонецФункции

//////////////////////////////////////////////////////////////////////////////////
// Печать с использованием макетов в формате Office Open XML.
//
// Описание структур данных:
//
// Макет - структура, используемая для хранения областей, разделов и колонтитулов из исходного шаблона.
//  - ИмяКаталога - Строка - путь, куда распаковывается контейнер DOCX шаблона для дальнейшего анализа.
//  - СтруктураДокумента - Структура - коллекция, куда собирается информация по областям, разделам и колонтитулам,
//                                     входящих в шаблон.
//
// ПечатнаяФорма - структура, используемая для вывода и заполнения областей из структуры "Макет".
//  - ИмяКаталога - Строка - путь, куда помещается структура каталогов конечного документа для последующей сборки
//                           контейнера DOCX.
//  - СтруктураДокумента - Структура - коллекция, куда собирается информация по областям, разделам и колонтитулам,
//                                     выведенных в конечный документ.
//
// Структура документа
//  - ОбластиДокумента - Соответствие - коллекция шаблонов областей, в которой ключ - имя области в исходном шаблоне.
//  - Разделы - Соответствие - коллекция разделов шаблона, в которой ключ - номер раздела в исходном шаблоне.
//  - Колонтитулы - Соответствие - коллекция колонтитулов шаблона, в которой ключ - имя верхнего или нижнего колонтитула,
//                                 сформированное из исходного шаблона.
//  - ПрисоединенныеОбласти - Массив - коллекция заполненных и выведенных областей в конечном документе.
//  - ТипыКонтента - Строка - текст файла [Content_Types].xml из контейнера DOCX.
//  - СвязиКонтента - Строка - текст файла document.xml.rels из контейнера DOCX.
//  - ТаблицаСвязейКонтента - таблица значений - разобранный файл document.xml.rels по именам и
//                                               идентификаторам ресурсов.
//  - КаталогКартинок - Строка - путь для сохранения картинок в конечном документе.
//  - РасширенияКартинок - Массив - расширения добавленных изображений в конечный документ.
//  - ИдентификаторДокумента - Строка - идентификатор ревизии документа.
//
// Структура раздела
//  - Колонтитулы - Соответствие - коллекция верхних и нижних колонтитулов шаблона для конкретного раздела, в которой
//                                 ключ - имя колонтитула в исходном шаблоне.
//  - Текст - Строка - текст раздела в исходном шаблоне.
//  - Номер - Число - номер раздела в исходном шаблоне.
//
// Структура области
//  - Имя - Строка - имя области, заданное в исходном шаблоне.
//  - Текст - Строка - текст области, заданный в исходном шаблоне.
//  - НомерРаздела - Число - номер раздела в исходном шаблоне, в который входит область.
//
// Структура верхнего/нижнего колонтитула
//  - Имя - Строка - имя колонтитула, сформированное из исходного шаблона.
//  - ИмяВнутр - Строка - имя файла колонтитула из структуры контейнера DOCX исходного шаблона.
//  - Текст - Строка - текст колонтитула, заданный в исходном шаблоне.
//  - НомерРаздела - Число - номер раздела в исходном шаблоне, к которому относится колонтитул.
//

// Возвращает структуру печатной формы для формирования конечного документа.
//
// Параметры:
//  Макет - Структура - макет печатной формы.
//
// Возвращаемое значение:
//  Структура:
//   * ИмяКаталога        - Строка - путь, куда помещается структура каталогов конечного документа для последующей
//                                   сборки контейнера DOCX.
//   * СтруктураДокумента - см. ИнициализироватьДокумент
//
Функция ИнициализироватьПечатнуюФорму(Макет) Экспорт
	
	Если БезопасныйРежим() <> Ложь Тогда
		УстановитьОтключениеБезопасногоРежима(Истина);
	КонецЕсли;
	
	ИмяВременногоКаталога = ФайловаяСистема.СоздатьВременныйКаталог();
	
	КопироватьСодержимоеКаталога(Макет.ИмяКаталога, ИмяВременногоКаталога);
	
	СтруктураДокумента = ИнициализироватьДокумент();
	
	ПечатнаяФорма = Новый Структура;
	ПечатнаяФорма.Вставить("ИмяКаталога", ИмяВременногоКаталога);
	ПечатнаяФорма.Вставить("СтруктураДокумента", СтруктураДокумента);
	
	ИнициализироватьСтруктуруПечатнойФормы(ПечатнаяФорма, Макет);
	
	Возврат ПечатнаяФорма;
	
КонецФункции

// Возвращает структуру макета печатной формы.
// Файл макета заполняется на основе двоичных данных, переданных в параметрах функции.
//
// Параметры:
//  ДвоичныеДанныеМакета - ДвоичныеДанные - двоичные данные макета.
//
// Возвращаемое значение:
//  Структура - макет печатной формы.
//
Функция МакетИзДвоичныхДанных(ДвоичныеДанныеМакета) Экспорт
	
	Если БезопасныйРежим() <> Ложь Тогда
		УстановитьОтключениеБезопасногоРежима(Истина);
	КонецЕсли;
	
	Расширение = ОпределитьРасширениеФайлаДанныхПоСигнатуре(ДвоичныеДанныеМакета);
	Если Расширение <> "docx" Тогда
		ТекстОшибки = НСтр("ru = 'Макет шаблона офисного документа имеет неверный формат.'");
		ЗаписатьСобытияВЖурналРегистрации(СобытиеЖурналаРегистрации(), "Ошибка", ТекстОшибки);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	ИмяВременногоФайла = ПолучитьИмяВременногоФайла("docx");
	
	ИмяВременногоКаталога = ФайловаяСистема.СоздатьВременныйКаталог();
	
	ДвоичныеДанныеМакета.Записать(ИмяВременногоФайла);
	
	РазобратьКонтейнерДокументDOCX(ИмяВременногоФайла, ИмяВременногоКаталога);
	
	УдалитьФайлы(ИмяВременногоФайла);
	
	СтруктураДокумента = ИнициализироватьДокумент();
	
	Макет = Новый Структура;
	Макет.Вставить("ИмяКаталога",        ИмяВременногоКаталога);
	Макет.Вставить("СтруктураДокумента", СтруктураДокумента);
	
	ИнициализироватьСтруктуруМакета(Макет);
			
	Возврат Макет;
	
КонецФункции

#Область СКД

// Параметры:
//  ДвоичныеДанныеМакета - ДвоичныеДанные
// 
// Возвращаемое значение:
//  Структура:
//    * ИмяКаталога - Строка - временный каталог
//    * СтруктураДокумента - см. ИнициализироватьДокументСКД
//
Функция МакетИзДвоичныхДанныхСКД(ДвоичныеДанныеМакета) Экспорт
	
	Если БезопасныйРежим() <> Ложь Тогда
		УстановитьОтключениеБезопасногоРежима(Истина);
	КонецЕсли;
	
	Расширение = ОпределитьРасширениеФайлаДанныхПоСигнатуре(ДвоичныеДанныеМакета);
	Если Расширение <> "docx" Тогда
		ТекстОшибки = НСтр("ru = 'Макет шаблона офисного документа имеет неверный формат.'");
		ЗаписатьСобытияВЖурналРегистрации(СобытиеЖурналаРегистрации(), "Ошибка", ТекстОшибки);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	ИмяВременногоФайла = ПолучитьИмяВременногоФайла("docx");	
	ИмяВременногоКаталога = ФайловаяСистема.СоздатьВременныйКаталог();	
	ДвоичныеДанныеМакета.Записать(ИмяВременногоФайла);
	
	РазобратьКонтейнерДокументDOCX(ИмяВременногоФайла, ИмяВременногоКаталога);
	
	УдалитьФайлы(ИмяВременногоФайла);
	
	СтруктураДокумента = ИнициализироватьДокументСКД();
	
	Макет = Новый Структура;
	Макет.Вставить("ИмяКаталога",        ИмяВременногоКаталога);
	Макет.Вставить("СтруктураДокумента", СтруктураДокумента);
	
	ИнициализироватьСтруктуруМакетаСКД(Макет);
			
	Возврат Макет;
	
КонецФункции


// Инициализировать документ СКД.
// 
// Возвращаемое значение:
//  Структура - инициализировать документ версия параметры:
//   * Колонтитулы - Соответствие 
//   * ТипыКонтента - см. ДеревоДокумента
//   * СвязиКонтента - см. ДеревоДокумента
//   * КаталогКартинок - Строка
//   * РасширенияКартинок - Массив
//   * ИдентификаторДокумента - Строка
//   * ДеревоДокумента - см. ДеревоДокумента
//   * ПараметрыТекста - Массив
//   * Области - см. ТаблицаОбластейМакета
//
Функция ИнициализироватьДокументСКД()
	
	Результат = Новый Структура;
	Результат.Вставить("Колонтитулы",            Новый Соответствие);
	Результат.Вставить("ТипыКонтента",           Новый ДеревоЗначений);
	Результат.Вставить("СвязиКонтента", 		 Новый ДеревоЗначений);
	Результат.Вставить("МаксимальныйИдентификаторСвязи", 		 0);
	Результат.Вставить("Гиперссылки",            Новый Соответствие);
	Результат.Вставить("КаталогКартинок",        "");
	Результат.Вставить("РасширенияКартинок",     Новый Массив);
	Результат.Вставить("ИдентификаторДокумента", "");
	Результат.Вставить("ДеревоДокумента", 		 Новый ДеревоЗначений);
	Результат.Вставить("ПараметрыТекста",     	 Новый Массив);
	
	ТаблицаОбластей = ТаблицаОбластейМакета();
	Результат.Вставить("Области",     	 		 ТаблицаОбластей);	
	
	Возврат Результат;
	
КонецФункции

// Таблица областей макета.
// 
// Возвращаемое значение:
//  ТаблицаЗначений:
//   * УзелДереваДокумента - см. ДеревоДокумента
//   * УсловиеОбласти  - Строка
//   * Коллекция - Строка
//   * Индекс - Число
//   * ДеревоОбласти - см. ДеревоДокумента
//   * Параметры - Массив
//
Функция ТаблицаОбластейМакета()
	Перем ТаблицаОбластей;
	ТаблицаОбластей = Новый ТаблицаЗначений;
	ТаблицаОбластей.Колонки.Добавить("УзелДереваДокумента");
	ТаблицаОбластей.Колонки.Добавить("УсловиеОбласти");
	ТаблицаОбластей.Колонки.Добавить("Коллекция");
	ТаблицаОбластей.Колонки.Добавить("Индекс");
	ТаблицаОбластей.Колонки.Добавить("ДеревоОбласти");
	ТаблицаОбластей.Колонки.Добавить("Параметры");
	Возврат ТаблицаОбластей
КонецФункции


// Конвертировать параметры.
// 
// Параметры:
//  ДеревоДокумента - см. УправлениеПечатьюСлужебный.ПрочитатьXMLВДерево
//
Процедура КонвертироватьПараметры(ДеревоДокумента) Экспорт
			
	МассивУзловПараметров = Новый Массив;
	НайтиУзлыПоСодержимому(ДеревоДокумента, "w:fldChar", МассивУзловПараметров);
	
	Если Не МассивУзловПараметров.Количество() Тогда
		Возврат;
	КонецЕсли;
	
	МассивОбластей = Новый Массив;
	МассивОбласти  = Новый Массив;
	
	Для Каждого УзелПараметров Из МассивУзловПараметров Цикл
		ТипУзла = УзелПараметров.Атрибуты["w:fldCharType"];
		
		МассивОбласти.Добавить(УзелПараметров);
				
		Если ТипУзла = "end" Тогда
			МассивОбластей.Добавить(МассивОбласти);
			МассивОбласти  = Новый Массив;
		КонецЕсли;
		
	КонецЦикла;
	
	Для Каждого МассивОбласти Из МассивОбластей Цикл
		УзелНачала = МассивОбласти[0];  // СтрокаДереваЗначений из см. УправлениеПечатьюСлужебный.ПрочитатьXMLВДерево
		Если Не УзелНачала.Строки.Количество() Тогда
			Продолжить;
		КонецЕсли;	
		УзелВводаТекста = НайтиУзелПоСодержимому(УзелНачала, "w:textInput");
		УзелЗначения	= УзелВводаТекста.Строки[0];
		УзелНачала.Текст = "["+УзелЗначения.Атрибуты["w:val"]+"]";
		
		УзелНачала.Строки.Очистить();
		УзелНачала.ИмяТега = "w:t";
		УзелНачала.Атрибуты.Очистить();
		
		
		УзелОкончания = МассивОбласти[МассивОбласти.ВГраница()]; // СтрокаДереваЗначений из см. УправлениеПечатьюСлужебный.ПрочитатьXMLВДерево
		
		ПрогонНачала = УзелНачала.Родитель;
		ПрогонОкончания = УзелОкончания.Родитель;
		
		ИндексПрогонаНачала = ПрогонНачала.Родитель.Строки.Индекс(ПрогонНачала);
		ИндексПрогонаОкончания = ПрогонОкончания.Родитель.Строки.Индекс(ПрогонОкончания);
		
		УзловКУдалению = ИндексПрогонаОкончания - (ИндексПрогонаНачала+1);
		
		Для к = 0 По УзловКУдалению Цикл
			ПрогонНачала.Родитель.Строки.Удалить(ИндексПрогонаОкончания-к);
		КонецЦикла;
	КонецЦикла;
	
КонецПроцедуры

#КонецОбласти

// Очищает все файлы, связанные с печатной формой или макетом печатной формы.
// Параметры:
//  ПечатнаяФорма - Структура - печатная форма или макет печатной формы.
//
Процедура ЗакрытьСоединение(ПечатнаяФорма) Экспорт
	
	Попытка
		Если БезопасныйРежим() <> Ложь Тогда
			УстановитьОтключениеБезопасногоРежима(Истина);
		КонецЕсли;
		
		ФайловаяСистема.УдалитьВременныйКаталог(ПечатнаяФорма.ИмяКаталога);
	Исключение
		ЗаписатьСобытияВЖурналРегистрации(СобытиеЖурналаРегистрации(), "Ошибка", ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		ВызватьИсключение(НСтр("ru = 'Не удалось удалить временный каталог шаблона печатной формы по причине:'") + Символы.ПС 
			+ ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
	КонецПопытки;
	
КонецПроцедуры

// Собирает конечный документ из структуры печатной формы и формирует файл данных формата DOCX.
// Файл данных помещается во временное хранилище.
//
// Параметры:
//  ПечатнаяФорма - Структура
//
// Возвращаемое значение:
//  Строка - адрес сформированного документа во временном хранилище.
//
Функция СформироватьДокумент(ПечатнаяФорма) Экспорт
	
	Если БезопасныйРежим() <> Ложь Тогда
		УстановитьОтключениеБезопасногоРежима(Истина);
	КонецЕсли;
	
	КоличествоОбластей = ПечатнаяФорма.СтруктураДокумента.ПрисоединенныеОбласти.Количество();
	
	Если КоличествоОбластей = 0 Тогда
		УдалитьФайлы(ПечатнаяФорма.ИмяКаталога);
		Возврат Неопределено;
	КонецЕсли;
	
	ПутьКДокументу = СобратьФайлДокументаDOCX(ПечатнаяФорма);
	
	ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКДокументу);
	
	АдресХранилищаПечатнойФормы = ПоместитьВоВременноеХранилище(ДвоичныеДанные, Новый УникальныйИдентификатор);
	
	УдалитьФайлы(ПутьКДокументу);
	УдалитьФайлы(ПечатнаяФорма.ИмяКаталога);
	
	Возврат АдресХранилищаПечатнойФормы;
	
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Функции для получения областей из макета.

// Получает область из макета.
//
// Параметры:
//  Макет      - Структура - макет печатной формы.
//  ИмяОбласти - Строка - имя области в макете.
//
// Возвращаемое значение:
//  Структура - область макета.
//
Функция ПолучитьОбластьМакета(Макет, Знач ИмяОбласти) Экспорт
	
	Возврат ПолучитьИзСтруктурыДокументаОбластьДокумента(Макет.СтруктураДокумента, ИмяОбласти);
	
КонецФункции

// Получает область верхнего колонтитула первой области макета.
//
// Параметры:
//  Макет          - Структура - макет печатной формы;
//  ИмяОбласти - Строка - имя области в макете;
//  НомерРаздела   - Число - номер раздела, в который входит верхний колонтитул.
//
// Возвращаемое значение:
//  Структура - область верхнего колонтитула.
//
Функция ПолучитьОбластьВерхнегоКолонтитула(Макет, Знач ИмяОбласти = "ВерхнийКолонтитул", Знач НомерРаздела = 1) Экспорт
	
	Параметры = СтрРазделить(ИмяОбласти, "_");
	Если Параметры.Количество() = 2 Тогда
		ИмяОбласти = Параметры[0];
		Попытка
			НомерРаздела = Число(Параметры[1]);
		Исключение
			НомерРаздела = 1;
		КонецПопытки;
	КонецЕсли;
	
	Возврат ПолучитьИзСтруктурыДокументаКолонтитул(Макет.СтруктураДокумента, ИмяОбласти, НомерРаздела);
	
КонецФункции

// Получает область нижнего колонтитула первой области макета.
//
// Параметры:
//  Макет          - Структура - макет печатной формы;
//  ИмяОбласти - Строка - имя области в макете;
//  НомерРаздела   - Число - номер раздела, в который входит нижний колонтитул.
//
// Возвращаемое значение:
//  Структура - область нижнего колонтитула.
//
Функция ПолучитьОбластьНижнегоКолонтитула(Макет, Знач ИмяОбласти = "НижнийКолонтитул", Знач НомерРаздела = 1) Экспорт
	
	Параметры = СтрРазделить(ИмяОбласти, "_");
	Если Параметры.Количество() = 2 Тогда
		ИмяОбласти = Параметры[0];
		Попытка
			НомерРаздела = Число(Параметры[1]);
		Исключение
			НомерРаздела = 1;
		КонецПопытки;
	КонецЕсли;
	
	Возврат ПолучитьИзСтруктурыДокументаКолонтитул(Макет.СтруктураДокумента, ИмяОбласти, НомерРаздела);
	
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Функции для добавления областей к печатной форме.

// Добавляет нижний колонтитул в печатную форму из макета.
//
// Параметры:
//  ПечатнаяФорма - Структура
//  НижнийКолонтитул - Структура - область нижнего колонтитула.
//
// Возвращаемое значение:
//  Структура - область добавленного колонтитула.
//
Функция ДобавитьНижнийКолонтитул(ПечатнаяФорма, НижнийКолонтитул) Экспорт
	
	ДобавитьВСтруктуруДокументаКолонтитул(ПечатнаяФорма.СтруктураДокумента, НижнийКолонтитул);
	СтруктураКолонтитула = ПрисоединитьКСтруктуреДокументаКолонтитул(ПечатнаяФорма.СтруктураДокумента, НижнийКолонтитул);
	
	Возврат СтруктураКолонтитула;
	
КонецФункции

// Заполняет параметры нижнего колонтитула в печатной форме из макета.
//
// Параметры:
//  ПечатнаяФорма - см. ИнициализироватьПечатнуюФорму
//  НижнийКолонтитул    - Структура - область нижнего колонтитула;
//  ДанныеОбъекта - Структура - данные объекта для заполнения.
//
Процедура ЗаполнитьПараметрыНижнегоКолонтитула(ПечатнаяФорма, НижнийКолонтитул, ДанныеОбъекта = Неопределено) Экспорт
	
	Если НЕ ТипЗнч(ДанныеОбъекта) = Тип("Структура") Тогда
		Возврат;
	КонецЕсли;
	
	ЗаполнитьПараметрыОбласти(ПечатнаяФорма, НижнийКолонтитул, ДанныеОбъекта);
	ЗаполнитьПараметрыГиперссылок(ПечатнаяФорма, НижнийКолонтитул, ДанныеОбъекта);
	
КонецПроцедуры

// Добавляет верхний колонтитул в печатную форму из макета.
//
// Параметры:
//  ПечатнаяФорма - Структура
//  ВерхнийКолонтитул - Структура - область колонтитула.
//
// Возвращаемое значение:
//  Структура - область добавленного колонтитула.
//
Функция ДобавитьВерхнийКолонтитул(ПечатнаяФорма, ВерхнийКолонтитул) Экспорт
	
	ДобавитьВСтруктуруДокументаКолонтитул(ПечатнаяФорма.СтруктураДокумента, ВерхнийКолонтитул);
	СтруктураКолонтитула = ПрисоединитьКСтруктуреДокументаКолонтитул(ПечатнаяФорма.СтруктураДокумента, ВерхнийКолонтитул);
	
	Возврат СтруктураКолонтитула;
	
КонецФункции

// Заполняет параметры верхнего колонтитула в печатной форме из макета.
//
// Параметры:
//  ПечатнаяФорма - см. ИнициализироватьПечатнуюФорму
//  ВерхнийКолонтитул    - Структура - область колонтитула;
//  ДанныеОбъекта - Структура - данные объекта для заполнения.
//
Процедура ЗаполнитьПараметрыВерхнегоКолонтитула(ПечатнаяФорма, ВерхнийКолонтитул, ДанныеОбъекта = Неопределено) Экспорт
	
	Если НЕ ТипЗнч(ДанныеОбъекта) = Тип("Структура") Тогда
		Возврат;
	КонецЕсли;
	
	ЗаполнитьПараметрыОбласти(ПечатнаяФорма, ВерхнийКолонтитул, ДанныеОбъекта);
	ЗаполнитьПараметрыГиперссылок(ПечатнаяФорма, ВерхнийКолонтитул, ДанныеОбъекта);
	
КонецПроцедуры

// Добавляет область в печатную форму из макета, при этом заменяя
// параметры в области значениями из данных объекта.
// Применяется при одиночном выводе области.
//
// Параметры:
//  ПечатнаяФорма       - см. ИнициализироватьПечатнуюФорму
//  ОбластьМакета       - Структура
//  ПереходНаСледСтроку - Булево - определяет, требуется ли вставлять разрыв после вывода области.
//
// Возвращаемое значение:
//  Структура - присоединенная область.
//
Функция ПрисоединитьОбласть(ПечатнаяФорма, ОбластьМакета, Знач ПереходНаСледСтроку = Ложь) Экспорт
	
	ДобавитьВСтруктуруДокументаОбластьДокумента(ПечатнаяФорма.СтруктураДокумента, ОбластьМакета);
	СтруктураОбласти = ПрисоединитьКСтруктуреДокументаОбластьДокумента(ПечатнаяФорма.СтруктураДокумента, ОбластьМакета);
	
	Если ПереходНаСледСтроку Тогда
		ВставитьРазрывНаНовуюСтроку(ПечатнаяФорма);
	КонецЕсли;
	
	Возврат СтруктураОбласти;
	
КонецФункции

// Заменяет параметры в области значениями из данных объекта.
//
// Параметры:
//  ПечатнаяФорма - см. ИнициализироватьПечатнуюФорму
//  ОбластьМакета - Структура
//  ДанныеОбъекта - Структура - данные объекта для заполнения.
//
Процедура ЗаполнитьПараметры(ПечатнаяФорма, ОбластьМакета, ДанныеОбъекта = Неопределено) Экспорт
	
	Если НЕ ТипЗнч(ДанныеОбъекта) = Тип("Структура") Тогда
		Возврат;
	КонецЕсли;
	
	ЗаполнитьПараметрыГиперссылок(ПечатнаяФорма, ОбластьМакета, ДанныеОбъекта);
	ЗаполнитьПараметрыОбласти(ПечатнаяФорма, ОбластьМакета, ДанныеОбъекта);
	
КонецПроцедуры

// Добавляет область коллекции в печатную форму из макета, при этом заменяя
// параметры в области значениями из данных объекта.
// Применяется при выводе данных списка (маркированного или нумерованного) или таблицы.
//
// Параметры:
//  ПечатнаяФорма       - Структура
//  ОбластьМакета       - Структура
//  ДанныеОбъекта       - Структура - данные объекта для заполнения.
//  ПереходНаСледСтроку - Булево - определяет, требуется ли вставлять разрыв после вывода областей всей коллекции.
//
Процедура ПрисоединитьИЗаполнитьНабор(ПечатнаяФорма, ОбластьМакета, ДанныеОбъекта = Неопределено,
	Знач ПереходНаСледСтроку = Ложь) Экспорт
	
	Если НЕ ТипЗнч(ДанныеОбъекта) = Тип("Массив") Тогда
		Возврат;
	КонецЕсли;
	
	Если ДанныеОбъекта.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	Для Каждого ДанныеСтроки Из ДанныеОбъекта Цикл
		
		Если НЕ ТипЗнч(ДанныеСтроки) = Тип("Структура") Тогда
			Продолжить;
		КонецЕсли;
		
		Область = ПрисоединитьОбласть(ПечатнаяФорма, ОбластьМакета);
		ЗаполнитьПараметры(ПечатнаяФорма, Область, ДанныеСтроки);
		
	КонецЦикла;
	
	Если ПереходНаСледСтроку Тогда
		ВставитьРазрывНаНовуюСтроку(ПечатнаяФорма);
	КонецЕсли;
	
КонецПроцедуры

// Вставляет разрыв на следующую строку.
//
// Параметры:
//  ПечатнаяФорма - Структура
//
Процедура ВставитьРазрывНаНовуюСтроку(ПечатнаяФорма) Экспорт
	
	Абзац = ПечатнаяФорма.СтруктураДокумента.ОбластиДокумента.Получить("Абзац");
	
	Если Абзац <> Неопределено Тогда
		
		Абзац.НомерРаздела = 1;
		
		Количество = ПечатнаяФорма.СтруктураДокумента.ПрисоединенныеОбласти.Количество();
		
		Если Количество <> 0 Тогда
			Абзац.НомерРаздела = ПечатнаяФорма.СтруктураДокумента.ПрисоединенныеОбласти[Количество - 1].НомерРаздела;
		КонецЕсли;
		
		ПрисоединитьОбласть(ПечатнаяФорма, Абзац, Ложь);
		
	КонецЕсли;
	
КонецПроцедуры

#Область РаботаСоСтруктуройДокумента

// Возвращаемое значение:
//   Структура:
//   * ИдентификаторДокумента - Строка
//   * РасширенияКартинок - Массив
//   * КаталогКартинок - Строка
//   * ТаблицаСвязейКонтента - ТаблицаЗначений
//   * СвязиКонтента - Строка
//   * ТипыКонтента - Строка
//   * ПрисоединенныеОбласти - Массив
//   * Колонтитулы - Соответствие из КлючИЗначение:
//    ** Ключ - Строка
//    ** Значение - см. ОбластьКолонтитула
//   * Разделы - Соответствие
//   * ОбластиДокумента - Соответствие
//
Функция ИнициализироватьДокумент() Экспорт
	
	Результат = Новый Структура;
	Результат.Вставить("ОбластиДокумента",       Новый Соответствие);
	Результат.Вставить("Разделы",                Новый Соответствие);
	Результат.Вставить("Колонтитулы",            Новый Соответствие);
	Результат.Вставить("ПрисоединенныеОбласти",  Новый Массив);
	Результат.Вставить("ТипыКонтента",           "");
	Результат.Вставить("СвязиКонтента",          "");
	Результат.Вставить("ТаблицаСвязейКонтента",  Новый ТаблицаЗначений);
	Результат.Вставить("КаталогКартинок",        "");
	Результат.Вставить("РасширенияКартинок",     Новый Массив);
	Результат.Вставить("ИдентификаторДокумента", "");
	
	ОписаниеЧисла  = Новый ОписаниеТипов("Число");
	ОписаниеСтроки = Новый ОписаниеТипов("Строка");
	
	Результат.ТаблицаСвязейКонтента.Колонки.Добавить("ИмяРесурса",   ОписаниеСтроки);
	Результат.ТаблицаСвязейКонтента.Колонки.Добавить("ИдРесурса",    ОписаниеСтроки);
	Результат.ТаблицаСвязейКонтента.Колонки.Добавить("НомерРесурса", ОписаниеЧисла);
	
	Возврат Результат;
	
КонецФункции

Функция ОбластьРаздела()
	
	Результат = Новый Структура;
	Результат.Вставить("Колонтитулы", Новый Соответствие);
	Результат.Вставить("Текст",       "");
	Результат.Вставить("Номер",       1);
	
	Возврат Результат;
	
КонецФункции

Функция ОбластьДокумента()
	
	Результат = Новый Структура;
	Результат.Вставить("Имя",          "");
	Результат.Вставить("Текст",        "");
	Результат.Вставить("НомерРаздела", 1);
	Результат.Вставить("Гиперссылки",  Новый Массив);
	
	Возврат Результат;
	
КонецФункции

// Возвращаемое значение:
//   Структура:
//   * НомерРаздела - Число
//   * Текст - Строка
//   * ИмяВнутр - Строка
//   * Имя - Строка
//   * Гиперссылки - Массив
//
Функция ОбластьКолонтитула()
	
	Результат = Новый Структура;
	Результат.Вставить("Имя",          "");
	Результат.Вставить("ИмяВнутр",     "");
	Результат.Вставить("Текст",        "");
	Результат.Вставить("НомерРаздела", 1);
	Результат.Вставить("Гиперссылки",  Новый Массив);
	
	Возврат Результат;
	
КонецФункции

Функция ДобавитьВСтруктуруДокументаРаздел(СтруктураДокумента, Раздел)
	
	СтруктураРаздела = ОбластьРаздела();
	ЗаполнитьЗначенияСвойств(СтруктураРаздела, Раздел);
	СтруктураДокумента.Разделы.Вставить(СтруктураРаздела.Номер, СтруктураРаздела);
	Возврат СтруктураРаздела;
	
КонецФункции

Функция ДобавитьВСтруктуруДокументаОбластьДокумента(СтруктураДокумента, Область)
	
	СтруктураОбласти = ОбластьДокумента();
	ЗаполнитьЗначенияСвойств(СтруктураОбласти, Область);
	СтруктураДокумента.ОбластиДокумента.Вставить(СтруктураОбласти.Имя, СтруктураОбласти);
	Возврат СтруктураОбласти;
	
КонецФункции

Функция ДобавитьВСтруктуруДокументаКолонтитул(СтруктураДокумента, Колонтитул, Знач КлючКолонтитула = "")
	
	Раздел = СтруктураДокумента.Разделы.Получить(Колонтитул.НомерРаздела);
	
	Если Раздел = Неопределено Тогда
		Колонтитул.Вставить("Номер", Колонтитул.НомерРаздела);
		Раздел = ДобавитьВСтруктуруДокументаРаздел(СтруктураДокумента, Колонтитул);
	КонецЕсли;
	
	СтруктураКолонтитула = ОбластьКолонтитула();
	ЗаполнитьЗначенияСвойств(СтруктураКолонтитула, Колонтитул);
	
	Если ПустаяСтрока(КлючКолонтитула) Тогда
		КлючКолонтитула = СтруктураКолонтитула.Имя + "_" + Формат(СтруктураКолонтитула.НомерРаздела, "ЧГ=0");
	КонецЕсли;
	
	СтруктураДокумента.Колонтитулы.Вставить(КлючКолонтитула, СтруктураКолонтитула);
	
	Возврат СтруктураКолонтитула;
	
КонецФункции

Функция ПрисоединитьКСтруктуреДокументаОбластьДокумента(СтруктураДокумента, Область)
	
	СтруктураОбласти = ОбластьДокумента();
	ЗаполнитьЗначенияСвойств(СтруктураОбласти, Область);
	
	СтруктураДокумента.ПрисоединенныеОбласти.Добавить(СтруктураОбласти);
	
	Возврат СтруктураОбласти;
	
КонецФункции

Функция ПрисоединитьКСтруктуреДокументаКолонтитул(СтруктураДокумента, Колонтитул)
	
	СтруктураКолонтитула = ОбластьКолонтитула();
	ЗаполнитьЗначенияСвойств(СтруктураКолонтитула, Колонтитул);
	
	Раздел = СтруктураДокумента.Разделы.Получить(СтруктураКолонтитула.НомерРаздела);
	
	Если Раздел = Неопределено Тогда
		СтруктураКолонтитула.Вставить("НомерРаздела", 1);
		Раздел = СтруктураДокумента.Разделы.Получить(1);
	КонецЕсли;
	
	КлючКолонтитула = СтруктураКолонтитула.Имя + "_" + Формат(СтруктураКолонтитула.НомерРаздела, "ЧГ=0");
	Раздел.Колонтитулы.Вставить(КлючКолонтитула, СтруктураКолонтитула);
	Возврат СтруктураКолонтитула;
	
КонецФункции

Функция ПолучитьИзСтруктурыДокументаОбластьДокумента(СтруктураДокумента, ИмяОбласти)
	
	Возврат СтруктураДокумента.ОбластиДокумента.Получить(ИмяОбласти);
	
КонецФункции

Функция ПолучитьИзСтруктурыДокументаКолонтитул(СтруктураДокумента, ИмяКолонтитула, НомерРаздела = 1)
	
	КлючКолонтитула = ИмяКолонтитула + "_" + Формат(НомерРаздела, "ЧГ=0");
	Возврат СтруктураДокумента.Колонтитулы.Получить(КлючКолонтитула);
	
КонецФункции

Процедура ДобавитьСтрокуВТаблицуСвязейКонтента(СтруктураДокумента, ИмяРесурса, ИдРесурса, НомерРесурса)
	
	НоваяСтрока = СтруктураДокумента.ТаблицаСвязейКонтента.Добавить();
	НоваяСтрока.ИмяРесурса   = ИмяРесурса;
	НоваяСтрока.ИдРесурса    = ИдРесурса;
	НоваяСтрока.НомерРесурса = НомерРесурса;
	
КонецПроцедуры

#КонецОбласти

#Область РаботаСOfficeOpenXML

#Область СКД

#Область ОбъединениеДокументов

Функция ОбъединитьОфисныеДокументы(ОфисныеДокументы, АдресЕдиногоДокумента)
	
	ИтоговаяПечатнаяФорма = Неопределено;
	
	Для каждого ОфисныйДокумент Из ОфисныеДокументы Цикл
		ДеревоМакета = УправлениеПечатью.ИнициализироватьМакетОфисногоДокументаСКД(ОфисныйДокумент.Значение);
		СтруктураДокумента = ДеревоМакета.СтруктураДокумента;
		СоответствиеСсылок = Новый Соответствие;

		СсылкиДляПоиска = ПолучитьСсылкиДляПоискаКонтента(СтруктураДокумента, ИтоговаяПечатнаяФорма = Неопределено);
		
		СсылкиДляПоиска = МассивВСоответствие(СсылкиДляПоиска);
		
		ВыделитьСсылки(СтруктураДокумента.ДеревоДокумента, СоответствиеСсылок, СсылкиДляПоиска);
		
		Если ИтоговаяПечатнаяФорма = Неопределено Тогда
			Для к = 1 По СсылкиДляПоиска.Количество() Цикл
				ИмяСвойства = "rId"+ Формат(к, "ЧГ=");
				Если СоответствиеСсылок.Получить(ИмяСвойства) = Неопределено Тогда
					СоответствиеСсылок.Вставить(ИмяСвойства, Новый Соответствие);
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;
		
		Если ИтоговаяПечатнаяФорма = Неопределено Тогда
			СтруктураСсылокИтоговогоДокумента = ОбщегоНазначения.СкопироватьРекурсивно(СоответствиеСсылок);
			ИтоговаяПечатнаяФорма = ОбщегоНазначения.СкопироватьРекурсивно(ДеревоМакета);
			СтруктураИтоговогоДокумента = ИтоговаяПечатнаяФорма.СтруктураДокумента;
		Иначе                           
			Для Каждого СсылкиВДокументе Из СоответствиеСсылок Цикл
				НовыйКлюч = ПодобратьУникальныйКлюч(СсылкиВДокументе.Ключ, СтруктураСсылокИтоговогоДокумента);
				Если НовыйКлюч <> СсылкиВДокументе.Ключ Тогда
					ЗаменитьУпоминания(СсылкиВДокументе, НовыйКлюч);
				КонецЕсли;
				ОбработатьСтруктуру(СсылкиВДокументе.Ключ, НовыйКлюч, ИтоговаяПечатнаяФорма, ДеревоМакета);
				СтруктураСсылокИтоговогоДокумента.Вставить(НовыйКлюч, ОбщегоНазначения.СкопироватьРекурсивно(СсылкиВДокументе.Значение));
			КонецЦикла;
			
			УзелDocumentНовогоДокумента = СтруктураДокумента.ДеревоДокумента.Строки[0]; // СтрокаТаблицыЗначений из см. УправлениеПечатьюСлужебный.ПрочитатьXMLВДерево
			УзелDocumentИтоговогоДокумента = СтруктураИтоговогоДокумента.ДеревоДокумента.Строки[0]; 
			
			УзелBodyНовогоДокумента 	= УзелDocumentНовогоДокумента.Строки[0]; 
			УзелBodyИтоговогоДокумента 	= УзелDocumentИтоговогоДокумента.Строки[0]; 

			УзелОкончанияРаздела = НайтиУзел(УзелBodyИтоговогоДокумента, -1, "w:sectPr");    
			
			ИндексДобавленияРаздела = УзелBodyИтоговогоДокумента.Строки.Индекс(УзелОкончанияРаздела);
			
			ДобавитьУзелОписанияРаздела(УзелBodyИтоговогоДокумента, ИндексДобавленияРаздела, УзелОкончанияРаздела);
			УзелBodyИтоговогоДокумента.Строки.Удалить(УзелОкончанияРаздела);
			
			Для Каждого УзелДобавления Из УзелBodyНовогоДокумента.Строки Цикл
				ИндексДобавленияРаздела = ИндексДобавленияРаздела + 1;
				ДобавляемыйУзел = СкопироватьУзел(УзелBodyИтоговогоДокумента, ИндексДобавленияРаздела, УзелДобавления);
				СоздатьПоследующие(ДобавляемыйУзел, УзелДобавления);
			КонецЦикла;
			УдалитьФайлы(ДеревоМакета.ИмяКаталога);
		КонецЕсли;
	КонецЦикла;
	
	Возврат ПолучитьПечатнуюФорму(ИтоговаяПечатнаяФорма, АдресЕдиногоДокумента);

КонецФункции  

Функция ПолучитьСсылкиДляПоискаКонтента(СтруктураДокумента, ВсеСсылки = Ложь)
	МассивСсылокДляПоиска = Новый Массив;
	МассивНайденныхУзлов = Новый Массив;

	МассивИскомых = Новый Массив;
	МассивИскомых.Добавить("http://schemas.openxmlformats.org/officeDocument/2006/relationships/header");
	МассивИскомых.Добавить("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
	МассивИскомых.Добавить("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer");
	МассивИскомых.Добавить("http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" );
	
	ДеревоСвязей = СтруктураДокумента.СвязиКонтента;
	
	Если ВсеСсылки Тогда
		НайтиУзлыПоСодержимому(ДеревоСвязей, "Relationship", МассивНайденныхУзлов);
	Иначе
		ПараметрыПоискаУзлов = ПараметрыПоискаУзлов();
		ПараметрыПоискаУзлов.ИмяАтрибута = "Type";
		ПараметрыПоискаУзлов.ЗначенияАтрибута = МассивИскомых;
		НайтиУзлыПоСодержимому(ДеревоСвязей, "Relationship", МассивНайденныхУзлов, ПараметрыПоискаУзлов);
	КонецЕсли; 
	
	Для Каждого НайденныйУзел Из МассивНайденныхУзлов Цикл
		МассивСсылокДляПоиска.Добавить(НайденныйУзел.Атрибуты["Id"]);
	КонецЦикла; 
	
	МассивСсылокДляПоиска = ОбщегоНазначенияКлиентСервер.СвернутьМассив(МассивСсылокДляПоиска);

	Возврат МассивСсылокДляПоиска;
КонецФункции

Процедура ЗаменитьУпоминания(СсылкиВДокументе, НовыйКлюч)
	Для Каждого СсылкаВДокументе Из СсылкиВДокументе.Значение Цикл
		ИсправляемыйУзел = СсылкаВДокументе.Ключ;
		Для Каждого Атрибут Из СсылкаВДокументе.Значение Цикл
			ИсправляемыйУзел.Атрибуты.Вставить(Атрибут.Ключ, НовыйКлюч);
		КонецЦикла;
	КонецЦикла;
КонецПроцедуры
	
Процедура ОбработатьСтруктуру(ИсходныйКлюч, НовыйКлюч, Приемник, Источник, Кодировка = "UTF-8")
	
	СтруктураДокументаПриемника = Приемник.СтруктураДокумента;
	СтруктураДокументаИсточника = Источник.СтруктураДокумента; 
	
	ДеревоСвязейИсточника = СтруктураДокументаИсточника.СвязиКонтента;
	ДеревоСвязейПриемника = СтруктураДокументаПриемника.СвязиКонтента;
	
	УзелИсточника = НайтиУзелПоСодержимому(ДеревоСвязейИсточника, "Relationship", "Id", ИсходныйКлюч);
	ИсходноеИмяРесурса = УзелИсточника.Атрибуты["Target"];
	ИмяРесурсаДляПриема = ИсходноеИмяРесурса;
	
	Если УзелИсточника.Атрибуты["Type"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" Тогда
		
	Иначе
		Пока Истина Цикл
			НайденныйУзел = НайтиУзелПоСодержимому(ДеревоСвязейПриемника, "Relationship", "Target", ИмяРесурсаДляПриема); 
			Если НайденныйУзел = Неопределено Тогда
				Прервать;
			КонецЕсли;
		
			МассивИмениИсточника = СтрРазделить(ИмяРесурсаДляПриема, "/\.");
		    КороткоеИмяРесурса = МассивИмениИсточника[МассивИмениИсточника.ВГраница()-1];
		    
		    СтруктураКлюча = ПолучитьИмяБезЦифр(КороткоеИмяРесурса); 
			ШаблонИмени 	= СтруктураКлюча.ШаблонИмени;
			НомерРесурса 	= СтруктураКлюча.Номер;
			НомерРесурса 	= НомерРесурса + 1;
			ИмяРесурса		= СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонИмени, Формат(НомерРесурса, "ЧГ="));
			
			ПутьКРесурсу = "";
			Для к = 0 По МассивИмениИсточника.ВГраница() - 2 Цикл
				ПутьКРесурсу = ПутьКРесурсу + МассивИмениИсточника[к]+"/";
			КонецЦикла;
			ИмяРесурсаДляПриема = ПутьКРесурсу + ИмяРесурса +"."+МассивИмениИсточника[МассивИмениИсточника.ВГраница()];
		КонецЦикла;
		
		ИмяФайлаИсточника = Источник.ИмяКаталога + "word" + УстановитьРазделительПути("\"+ИсходноеИмяРесурса);
		ИмяФайлаПриемника = Приемник.ИмяКаталога + "word" + УстановитьРазделительПути("\"+ИмяРесурсаДляПриема);
		
		ФайлПриемник = Новый Файл(ИмяФайлаПриемника);
		КаталогФайлаПриемника = Новый Файл(ФайлПриемник.Путь);
		
		Если Не КаталогФайлаПриемника.Существует() Тогда   
			СоздатьКаталог(ФайлПриемник.Путь);
		КонецЕсли;
	
		КопироватьФайл(ИмяФайлаИсточника, ИмяФайлаПриемника);
	КонецЕсли;
	
	КореньСвязейПриемника = ДеревоСвязейПриемника.Строки[0];
	НоваяСвязь = СкопироватьУзел(КореньСвязейПриемника, КореньСвязейПриемника.Строки.Количество(), УзелИсточника);
	НоваяСвязь.Атрибуты.Вставить("Target", ИмяРесурсаДляПриема);
	НоваяСвязь.Атрибуты.Вставить("Id", НовыйКлюч);
	
	ДеревоТиповКонтентаПриемника = СтруктураДокументаПриемника.ТипыКонтента;
	ДеревоТиповКонтентаИсточника = СтруктураДокументаИсточника.ТипыКонтента;
	
	КореньПриемника = НайтиУзелПоСодержимому(ДеревоТиповКонтентаПриемника, "Types");

	Если СтрНайти(НоваяСвязь.Атрибуты["Type"], "header") ИЛИ СтрНайти(НоваяСвязь.Атрибуты["Type"], "footer") Тогда
		ИмяФайлаКолонтитулаИсточник = "/word/"+ИсходноеИмяРесурса;
		ИмяФайлаКолонтитулаПриемник = "/word/"+ИмяРесурсаДляПриема;
		
		УзелПереопределения = НайтиУзелПоСодержимому(ДеревоТиповКонтентаИсточника, "Override", "PartName", ИмяФайлаКолонтитулаИсточник);
		
		Если УзелПереопределения <> Неопределено Тогда
			НоваяТипКонтента = СкопироватьУзел(КореньПриемника, КореньПриемника.Строки.Количество(), УзелПереопределения);
			НоваяТипКонтента.Атрибуты.Вставить("PartName", ИмяФайлаКолонтитулаПриемник);
		КонецЕсли;
	ИначеЕсли НоваяСвязь.Атрибуты["Type"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Тогда
		
		МассивСловИмени = СтрРазделить(ИмяРесурсаДляПриема, ".", Истина);
		РасширениеИсточникаИсточника  = МассивСловИмени[МассивСловИмени.ВГраница()];
		
		УзелОпределениеИсточника = НайтиУзелПоСодержимому(ДеревоТиповКонтентаИсточника, "Default", "Extension", РасширениеИсточникаИсточника);
		УзелОпределениеПриемника = НайтиУзелПоСодержимому(ДеревоТиповКонтентаПриемника, "Default", "Extension", РасширениеИсточникаИсточника);
		
		Если УзелОпределениеИсточника <> Неопределено И УзелОпределениеПриемника = Неопределено Тогда
			НоваяТипКонтента = СкопироватьУзел(КореньПриемника, КореньПриемника.Строки.Количество(), УзелОпределениеИсточника);
		КонецЕсли;
	КонецЕсли;	

КонецПроцедуры  

Функция ПрочитатьСтрокуXMLВДерево(СтрокаXML)
	ЧтениеXML = ИнициализироватьЧтениеXML(СтрокаXML);
	Возврат ПрочитатьXMLВДерево(ЧтениеXML);
КонецФункции

// Поместить дерево в запись XML.
// 
// Параметры:
//  ЗаписьXML - ЗаписьXML - запись XML
//  Дерево - ДеревоЗначений:
//   * ИмяТега - Строка
//   * Текст - Строка
//   * ПолныйТекст - Строка
//   * Атрибуты - Соответствие
//
Процедура ПоместитьДеревоВЗаписьXML(ЗаписьXML, Дерево)
	Для каждого Подстрока Из Дерево.Строки Цикл
		ЗаписатьЭлемент(ЗаписьXML, Подстрока);	
	КонецЦикла;
КонецПроцедуры

Функция ПоместитьДеревоВСтрокуXML(Дерево)
	ЗаписьXML = ИнициализироватьЗаписьXML("");
	Для каждого Подстрока Из Дерево.Строки Цикл
		ЗаписатьЭлемент(ЗаписьXML, Подстрока);	
	КонецЦикла;
	Возврат ЗаписьXML.Закрыть();
КонецФункции

Функция ПодобратьУникальныйКлюч(Знач Ключ, Структура)
	СтруктураКлюча = ПолучитьИмяБезЦифр(Ключ); 
	ШаблонИмени = СтруктураКлюча.ШаблонИмени;
	НомерКлюча 	= СтруктураКлюча.Номер;
	
	Пока Структура.Получить(Ключ) <> Неопределено Цикл
		НомерКлюча = НомерКлюча + 1;
    	Ключ = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонИмени, Формат(НомерКлюча, "ЧГ="));
	КонецЦикла;
	Возврат Ключ;	
КонецФункции 

Функция ПолучитьИмяБезЦифр(Знач Имя)
	МассивКлюча = СтрРазделить(Имя, "0123456789", Ложь);
	Если МассивКлюча.Количество() > 1 Тогда
		ВызватьИсключение НСтр("ru = 'Неожиданный ключ'");
	КонецЕсли;
	Результат = Новый Структура ("ШаблонИмени, Номер");
	Результат.ШаблонИмени 	= МассивКлюча[0]+"%1";
	НеНужныеСимволы = СтрСоединить(МассивКлюча,"");
	МассивНомеров = СтрРазделить(Имя, НеНужныеСимволы, Ложь);
	Если МассивНомеров.Количество() > 1 Тогда
		ВызватьИсключение НСтр("ru = 'Неожиданный ключ, несколько номеров'");
	КонецЕсли;
	Результат.Номер	= Число(МассивНомеров[0]);
	Возврат Результат;
КонецФункции

Процедура ВыделитьСсылки(ДеревоМакета, СоответствиеСсылок, СсылкиДляПоиска)
	
	Для Каждого СтрокаДерева Из ДеревоМакета.Строки Цикл
		
		Для Каждого Атрибут Из СтрокаДерева.Атрибуты Цикл
			Если СсылкиДляПоиска.Получить(Атрибут.Значение) <> Неопределено Тогда 
				Упоминания = СоответствиеСсылок.Получить(Атрибут.Значение);
				Если Упоминания = Неопределено Тогда
					Упоминания = Новый Соответствие;
				КонецЕсли;
									
				Атрибуты = Упоминания.Получить(СтрокаДерева);
				Если Атрибуты = Неопределено Тогда
					Атрибуты = Новый Соответствие;
				КонецЕсли;
				Атрибуты.Вставить(Атрибут.Ключ, Атрибут.Значение);
				
				Упоминания.Вставить(СтрокаДерева, Атрибуты);
		
				СоответствиеСсылок.Вставить(Атрибут.Значение, Упоминания);
			КонецЕсли;
		КонецЦикла;
				
		ВыделитьСсылки(СтрокаДерева, СоответствиеСсылок, СсылкиДляПоиска);
	КонецЦикла;
КонецПроцедуры



// Параметры:
//  УзелРодителя - см. ДеревоДокумента
//  Индекс - Число 
//  Узел - см. ДеревоДокумента
//
Процедура ДобавитьУзелОписанияРаздела(УзелРодителя, Индекс, Узел)
	Если УзелРодителя.Строки.Количество() <= Индекс Тогда
		НовыйАбзац = УзелРодителя.Строки.Добавить();
	Иначе
		НовыйАбзац = УзелРодителя.Строки.Вставить(Индекс);
	КонецЕсли; 
	НовыйАбзац.ИмяТега = "w:p";
	НовыеСвойстваФорматирования = НовыйАбзац.Строки.Добавить();
	НовыеСвойстваФорматирования.ИмяТега = "w:pPr";
	
	НовыйРаздел = НовыеСвойстваФорматирования.Строки.Добавить();
	
	ЗаполнитьЗначенияСвойств(НовыйРаздел, Узел, "ИмяТега,Текст,ПолныйТекст");
	НовыйРаздел.Атрибуты = ОбщегоНазначения.СкопироватьРекурсивно(Узел.Атрибуты); 
	СоздатьПоследующие(НовыйРаздел, Узел);

КонецПроцедуры

#КонецОбласти

// Строит дерево значений по XML.
// 
// Параметры:
//  ЧтениеXML - ЧтениеXML
// 
// Возвращаемое значение:
//  ДеревоЗначений:
//   * ИмяТега - Строка - имя тега XML.
//   * Текст - Строка - текстовое значение тега.
//   * ПолныйТекст - Строка - текст всех подлежащих узлов
//   * Атрибуты - Соответствие - атрибуты узла
//  Гиперссылки - Соответствие
//
Функция ПрочитатьXMLВДерево(ЧтениеXML, Гиперссылки = Неопределено) Экспорт
	ЧтениеXML.ИгнорироватьПробелы = Ложь;
	Дерево = ДеревоДокумента();
	Если Гиперссылки <> Неопределено И Гиперссылки.Количество() = 0 Тогда
		Гиперссылки = Неопределено;
	КонецЕсли;
	ПрочитатьЗапись(ЧтениеXML, Дерево, Гиперссылки);
	Возврат Дерево;
КонецФункции

// Возвращаемое значение:
//  ДеревоЗначений:
//   * ИмяТега - Строка - имя тега XML
//   * Текст - Строка - текст содержащийся в теге XML
//   * ПолныйТекст - Строка - текст всех подчиненных узлов
//   * Атрибуты - Соответствие - атрибуты узла XML
//   * Индекс - Число - поле для индексации 
//
Функция ДеревоДокумента()
	Перем Дерево;
	Дерево = Новый ДеревоЗначений;
	Дерево.Колонки.Добавить("ИмяТега",  Новый ОписаниеТипов("Строка"));
	Дерево.Колонки.Добавить("Текст",  Новый ОписаниеТипов("Строка"));
	Дерево.Колонки.Добавить("ПолныйТекст",  Новый ОписаниеТипов("Строка"));
	Дерево.Колонки.Добавить("Атрибуты",  Новый ОписаниеТипов("Соответствие"));
	Дерево.Колонки.Добавить("Индекс",  Новый ОписаниеТипов("Число"));
	Возврат Дерево
КонецФункции

Функция ПрочитатьЗапись(ЧтениеXML, СтрокаДерева, Гиперссылки)
	ПолныйТекст = "";
	Пока ЧтениеXML.Прочитать() Цикл
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
			НоваяСтрока = СтрокаДерева.Строки.Добавить();
			НоваяСтрока.ИмяТега = ЧтениеXML.Имя;
			НоваяСтрока.Атрибуты = ПолучитьАтрибуты(ЧтениеXML);
			НоваяСтрока.Текст = "";
			НоваяСтрока.ПолныйТекст = ПрочитатьЗапись(ЧтениеXML, НоваяСтрока, Гиперссылки);
			
			Если Гиперссылки <> Неопределено И НоваяСтрока.ИмяТега = "w:hyperlink" Тогда
				ТекстСсылки = Гиперссылки[НоваяСтрока.Атрибуты["r:id"]];
				Если ТекстСсылки <> Неопределено Тогда
					НоваяСтрока.ПолныйТекст = ТекстСсылки + НоваяСтрока.ПолныйТекст;
				КонецЕсли;
			КонецЕсли;
			ПолныйТекст = ПолныйТекст + НоваяСтрока.ПолныйТекст;
			
		ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
			Возврат ПолныйТекст;
		ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
			Если ТипЗнч(СтрокаДерева) <> Тип("СтрокаДереваЗначений")
			    ИЛИ (СтрНачинаетсяС(ЧтениеXML.Значение, Символ(10))) Тогда 
				Продолжить;
			КонецЕсли;
			
			СтрокаДерева.Текст = СтрЗаменить(ЧтениеXML.Значение, Символ(160), " ");
			Если СтрНачинаетсяС(СтрокаДерева.Текст, "HYPERLINK ") Тогда           
				СтрокаДерева.Текст = РаскодироватьСтроку(ЧтениеXML.Значение, СпособКодированияСтроки.КодировкаURL);
			Иначе                                                                  
				СтрокаДерева.Текст = СтрЗаменить(ЧтениеXML.Значение, Символ(160), " ");
			КонецЕсли;
				
			СтрокаДерева.ПолныйТекст = СтрокаДерева.Текст;
			ПолныйТекст = ПолныйТекст + СтрокаДерева.ПолныйТекст;
			ЧтениеXML.Прочитать();
			Возврат ПолныйТекст;
		Иначе
			ВызватьИсключение (НСтр("ru = 'Не известный:'") + " " + ЧтениеXML.ТипУзла);
		КонецЕсли;
	КонецЦикла;
	Возврат ПолныйТекст;
КонецФункции  

Функция ПолучитьАтрибуты(ЧтениеXML)
	СоответствиеАтрибутов = Новый Соответствие;
	Пока ЧтениеXML.ПрочитатьАтрибут() Цикл
		СоответствиеАтрибутов.Вставить(ЧтениеXML.Имя, ЧтениеXML.Значение);
	КонецЦикла;
	Возврат СоответствиеАтрибутов;
КонецФункции

Процедура ИнициализироватьСтруктуруМакетаСКД(Макет)
	
	ИмяКаталога = Макет.ИмяКаталога;
	СтруктураДокумента = Макет.СтруктураДокумента;
	СтруктураДокумента.КаталогКартинок        = ИмяКаталога + УстановитьРазделительПути("\word\media\");
	
	ИзменяемыеФайлы = Новый Соответствие;
	ИзменяемыеФайлы.Вставить("СвязиКонтента", ИмяКаталога + УстановитьРазделительПути("\word\_rels\document.xml.rels"));
	ИзменяемыеФайлы.Вставить("ТипыКонтента",  ИмяКаталога + УстановитьРазделительПути("\[Content_Types].xml"));
	ИзменяемыеФайлы.Вставить("Документ",      ИмяКаталога + УстановитьРазделительПути("\word\document.xml"));
	
	КаталогСоСтруктуройФайла = ИмяКаталога + "word" + ПолучитьРазделительПути(); 
	
	Файл = Новый Файл(ИзменяемыеФайлы.Получить("СвязиКонтента"));
	Если Файл.Существует() Тогда
		ЧтениеXML = ИнициализироватьЧтениеXML(Файл.ПолноеИмя, 1);
		ДеревоXML = ПрочитатьXMLВДерево(ЧтениеXML);
		МассивУзловГиперссылок = Новый Массив;
		ПараметрыПоискаУзлов = ПараметрыПоискаУзлов();
		ПараметрыПоискаУзлов.ИмяАтрибута = "Type";
		ПараметрыПоискаУзлов.ЗначенияАтрибута = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
		НайтиУзлыПоСодержимому(ДеревоXML, "Relationship", МассивУзловГиперссылок, ПараметрыПоискаУзлов);
		СоответствиеГиперссылок = СтруктураДокумента.Гиперссылки;
		
		Для Каждого УзелГиперссылки Из МассивУзловГиперссылок Цикл
			ТекстСсылки = РаскодироватьСтроку(УзелГиперссылки.Атрибуты["Target"], СпособКодированияСтроки.КодировкаURL);
			ПараметрыСсылки = УправлениеПечатью.НайтиПараметрыВТексте(ТекстСсылки);
			ОбщегоНазначенияКлиентСервер.ДополнитьМассив(СтруктураДокумента.ПараметрыТекста, ПараметрыСсылки, Истина);
			ИдентификаторСсылки = УзелГиперссылки.Атрибуты["Id"];
			СоответствиеГиперссылок.Вставить(ИдентификаторСсылки, ТекстСсылки);
		КонецЦикла;         
		МаксимальныйИдентификатор = 0;
		МассивУзлов = Новый Массив;
		НайтиУзлыПоСодержимому(ДеревоXML, "Relationship", МассивУзлов);
		Для Каждого Узел Из МассивУзлов Цикл
			Идентификатор = Узел.Атрибуты["Id"];
			МассивЧастейИдентификатора = СтрРазделить(Идентификатор, "0123456789", Ложь);
			Идентификатор = Число(СтрЗаменить(Идентификатор, МассивЧастейИдентификатора[0], ""));
			МаксимальныйИдентификатор = Макс(Идентификатор, МаксимальныйИдентификатор);
		КонецЦикла;
		СтруктураДокумента.МаксимальныйИдентификаторСвязи = МаксимальныйИдентификатор; 
		СтруктураДокумента.СвязиКонтента = ДеревоXML;
	КонецЕсли;

	
	Файл = Новый Файл(КаталогСоСтруктуройФайла + "document.xml"); //@Non-NLS
	Если Файл.Существует() Тогда
		ЧтениеXML = ИнициализироватьЧтениеXML(Файл.ПолноеИмя, 1);
		СтруктураДокумента.ДеревоДокумента = ПрочитатьXMLВДерево(ЧтениеXML, СтруктураДокумента.Гиперссылки);
	
		ТекстXML = СтруктураДокумента.ДеревоДокумента.Строки[0].ПолныйТекст;
		СтруктураДокумента.ПараметрыТекста = УправлениеПечатью.НайтиПараметрыВТексте(ТекстXML);
		
	КонецЕсли;
	
	СтруктурныеФайлы = НайтиФайлы(КаталогСоСтруктуройФайла, "*.xml");
	Для Каждого Файл Из СтруктурныеФайлы Цикл
		Если НЕ (Лев(Файл.ИмяБезРасширения, 6) = "header") И НЕ (Лев(Файл.ИмяБезРасширения, 6) = "footer") Тогда
			Продолжить;
		КонецЕсли;
		
		ЧтениеXML = ИнициализироватьЧтениеXML(Файл.ПолноеИмя, 1);
		
		ДеревоXML = ПрочитатьXMLВДерево(ЧтениеXML, СтруктураДокумента.Гиперссылки);
		
		СтруктураДокумента.Колонтитулы.Вставить(Файл.ИмяБезРасширения, ДеревоXML);
		
		ТекстXML = ДеревоXML.Строки[0].ПолныйТекст;
		ОбщегоНазначенияКлиентСервер.ДополнитьМассив(СтруктураДокумента.ПараметрыТекста, УправлениеПечатью.НайтиПараметрыВТексте(ТекстXML), Истина);
		
	КонецЦикла;
		
	Файл = Новый Файл(ИзменяемыеФайлы.Получить("ТипыКонтента"));
	Если Файл.Существует() Тогда
		ЧтениеXML = ИнициализироватьЧтениеXML(Файл.ПолноеИмя, 1);
		ДеревоXML = ПрочитатьXMLВДерево(ЧтениеXML);
		СтруктураДокумента.ТипыКонтента = ДеревоXML;
	КонецЕсли;
	
КонецПроцедуры

Функция ПолучитьУзел(Дерево, Знач Путь) Экспорт
	МассивПути = СтрРазделить(Путь, "/", Ложь);
	МассивНайденныхСтрок = Дерево.Строки.НайтиСтроки(Новый Структура("ИмяТега", МассивПути[0]), Ложь);
	Если МассивНайденныхСтрок.Количество() Тогда
		Если МассивПути.Количество() = 1 Тогда
			Возврат МассивНайденныхСтрок[0];
		ИначеЕсли МассивПути.Количество() Тогда
			МассивПути.Удалить(0);
			Возврат ПолучитьУзел(МассивНайденныхСтрок[0], СтрСоединить(МассивПути, "/"));
		КонецЕсли;
	КонецЕсли;
	Возврат Неопределено;
КонецФункции    

Функция ПолучитьУзлыТекстов(УзелДокумента, СоответствиеУзлов = Неопределено) Экспорт
	Если СоответствиеУзлов = Неопределено Тогда
		СоответствиеУзлов = Новый Соответствие();
	КонецЕсли;
	
	Если УзелДокумента.ИмяТега = "w:t" Тогда
		СоответствиеУзлов.Вставить(УзелДокумента, УзелДокумента.Текст);
	КонецЕсли;
	
	Для Каждого ДочернийУзел Из УзелДокумента.Строки Цикл
		ПолучитьУзлыТекстов(ДочернийУзел, СоответствиеУзлов);		
	КонецЦикла;
	
	Возврат СоответствиеУзлов;
КонецФункции

Процедура ПроиндексироватьУзлы(ДеревоДокумента, Счетчик = 0) Экспорт
	Для Каждого Строка Из ДеревоДокумента.Строки Цикл
		Строка.Индекс = Счетчик;
		Счетчик = Счетчик + 1;
		ПроиндексироватьУзлы(Строка, Счетчик);
	КонецЦикла;
КонецПроцедуры

Процедура НайтиОбласти(СтруктураДокумента, ИменаТабличныхЧастейОбъекта) Экспорт
	
	Области = СтруктураДокумента.Области;
	ДеревоДокумента = СтруктураДокумента.ДеревоДокумента;
	
	НайденныеОбластиНачало = Новый Массив;
	НайденныеОбластиОкончание = Новый Массив;
	НайтиУзлы(ДеревоДокумента, "{"+ИмяТегаУсловие(), НайденныеОбластиНачало);
	НайтиУзлы(ДеревоДокумента, "{/"+ИмяТегаУсловие(), НайденныеОбластиОкончание);
	
	Для Каждого ИмяТабличнойЧасти Из ИменаТабличныхЧастейОбъекта Цикл
		НайденныеОбласти = Новый Массив;
		НайтиУзлы(ДеревоДокумента, "["+ИмяТабличнойЧасти+".", НайденныеОбласти);
		Для Каждого Область Из НайденныеОбласти Цикл
			Если НайденныеОбластиНачало.Найти(Область) <> Неопределено Тогда
				Продолжить;
			КонецЕсли;
			УзелНачалаТабличнойОбласти = НайтиКореньТабличнойОбласти(Область);
			Если Области.Найти(УзелНачалаТабличнойОбласти, "УзелДереваДокумента") = Неопределено Тогда
				НоваяОбласть = Области.Добавить();
				НоваяОбласть.УзелДереваДокумента = УзелНачалаТабличнойОбласти;
				НоваяОбласть.Коллекция = ИмяТабличнойЧасти;
				НоваяОбласть.Индекс = НоваяОбласть.УзелДереваДокумента.Индекс;
			КонецЕсли;
			
			УзелОкончанияТабличнойОбласти = ПолучитьСледующийУзел(УзелНачалаТабличнойОбласти);
			Если Области.Найти(УзелОкончанияТабличнойОбласти, "УзелДереваДокумента") = Неопределено Тогда
				НоваяОбласть = Области.Добавить();
				НоваяОбласть.УзелДереваДокумента = УзелОкончанияТабличнойОбласти;
				НоваяОбласть.Индекс = НоваяОбласть.УзелДереваДокумента.Индекс;
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
	
	ИндексыНайденныхОбластейНачало = ПолучитьИндексыМассиваУзлов(НайденныеОбластиНачало);
	ИндексыНайденныхОбластейОкончание = ПолучитьИндексыМассиваУзлов(НайденныеОбластиОкончание);
	
	Для Каждого ИндексНайденнойОбластиНачало Из ИндексыНайденныхОбластейНачало Цикл
		ОбластьНачала = ДеревоДокумента.Строки.Найти(ИндексНайденнойОбластиНачало, "Индекс", Истина);
		Для Каждого ИндексНайденнойОбластиОкончание Из ИндексыНайденныхОбластейОкончание Цикл
			ОбластьОкончания = ДеревоДокумента.Строки.Найти(ИндексНайденнойОбластиОкончание, "Индекс", Истина);
			Если ИндексНайденнойОбластиНачало < ИндексНайденнойОбластиОкончание Тогда
				Прервать;
			КонецЕсли;
		КонецЦикла;
		
		УсловиеОбласти = УсловиеОбласти(ОбластьНачала);
		Если ОбластьОкончания = Неопределено Тогда
			ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru='В макете документа нет окончания условной области ""%1"".'"), УсловиеОбласти);
		КонецЕсли;
		
		ОбластьКоллекции = Неопределено;
		ОкончанияУсловныхОбластей = Новый Массив;
		УдаляемыеОбласти = Новый Массив;
		Для Каждого Область Из Области Цикл
			Если Область.Индекс >= ИндексНайденнойОбластиОкончание Или ИндексНайденнойОбластиНачало >= Область.Индекс Тогда
				Продолжить;
			КонецЕсли;
			Если ЗначениеЗаполнено(Область.Коллекция) Тогда
				ОбластьКоллекции = Область;
			КонецЕсли;
			ЭтоРодительОкончанияУсловия = 
				Область.УзелДереваДокумента.Строки.Найти(ИндексНайденнойОбластиОкончание, "Индекс", Истина) <> Неопределено;
			Если Не ЭтоРодительОкончанияУсловия Тогда
				Область.УсловиеОбласти = УсловиеОбласти;
				Продолжить;
			КонецЕсли;
				
			Если ОбластьКоллекции <> Неопределено Тогда
				УзелСледующейОбласти = ГраницаСледующейОбласти(ОбластьКоллекции.УзелДереваДокумента, Области);
				Если УзелСледующейОбласти <> Неопределено И УзелСледующейОбласти.Индекс < ИндексНайденнойОбластиОкончание Тогда
					СвойстваОбласти = Новый Структура("УзелДереваДокумента, УсловиеОбласти");
					СвойстваОбласти.УзелДереваДокумента = УзелСледующейОбласти;
					СвойстваОбласти.УсловиеОбласти = УсловиеОбласти;
					ОкончанияУсловныхОбластей.Добавить(СвойстваОбласти);
				КонецЕсли;
			КонецЕсли;
			
			УзелСледующейОбласти = ГраницаСледующейОбласти(ОбластьОкончания, Области);
			Если УзелСледующейОбласти = Неопределено Тогда
				УдаляемыеОбласти.Добавить(Область);
				Продолжить;
			КонецЕсли;
			Область.УзелДереваДокумента = УзелСледующейОбласти;
			Область.Индекс = Область.УзелДереваДокумента.Индекс;
		КонецЦикла;
		
		Для каждого Область Из УдаляемыеОбласти Цикл
			Области.Удалить(Область);
		КонецЦикла;
		
		Для Каждого СвойстваОбласти Из ОкончанияУсловныхОбластей Цикл
			НоваяОбласть = Области.Добавить();
			ЗаполнитьЗначенияСвойств(НоваяОбласть, СвойстваОбласти);
			НоваяОбласть.Индекс = НоваяОбласть.УзелДереваДокумента.Индекс;
		КонецЦикла;
		
		ДобавитьОбластьСУсловием(Области, ОбластьНачала);
		ОбластьОкончания = ДеревоДокумента.Строки.Найти(ИндексНайденнойОбластиОкончание, "Индекс", Истина);
		ДобавитьОбластьСУсловием(Области, ОбластьОкончания);
	КонецЦикла;
	
	УдалитьТегиУсловныхОбластей(ИндексыНайденныхОбластейНачало, ДеревоДокумента);
	УдалитьТегиУсловныхОбластей(ИндексыНайденныхОбластейОкончание, ДеревоДокумента);
	
	УзелНачала = ДеревоДокумента.Строки[0];
	Если Области.Найти(УзелНачала, "УзелДереваДокумента") = Неопределено Тогда
		НоваяОбласть = Области.Добавить();
		НоваяОбласть.УзелДереваДокумента = УзелНачала;
		НоваяОбласть.УсловиеОбласти = Неопределено;
		НоваяОбласть.Коллекция = "";
		НоваяОбласть.Индекс = НоваяОбласть.УзелДереваДокумента.Индекс;
	КонецЕсли;
		
	ДобавитьОбластиПереходныхУровней(Области, ДеревоДокумента);
	
	Для ИндексОбласти = 0 По Области.Количество()-1 Цикл
		ТекущаяОбласть = СтруктураДокумента.Области[ИндексОбласти];
		СтруктураОбласти = СтруктураОбластиИзМакета(ДеревоДокумента, Области, ИндексОбласти, СтруктураДокумента.Гиперссылки);
		ЗаполнитьЗначенияСвойств(ТекущаяОбласть, СтруктураОбласти);
	КонецЦикла;
	
КонецПроцедуры

Функция ПолучитьИндексыМассиваУзлов(МассивУзлов)
	Результат = Новый Массив;
	
	Для Каждого Узел Из МассивУзлов Цикл
		Результат.Добавить(Узел.Индекс);
	КонецЦикла;
	
	Возврат Результат;
КонецФункции

Функция СтруктураОбластиИзМакета(ДеревоМакета, Области, ИндексОбласти, Гиперссылки)
	ТекущаяОбласть = Области[ИндексОбласти];
	ИндексУзлаТекущейОбласти = ТекущаяОбласть.Индекс;
	УзелНачалаОбласти = ТекущаяОбласть.УзелДереваДокумента;
	РодительНачалаОбласти = УзелНачалаОбласти.Родитель; 
	Если РодительНачалаОбласти = Неопределено Тогда
		КоллекцияПеребора = ДеревоМакета.Строки;
	Иначе
		КоллекцияПеребора = РодительНачалаОбласти.Строки;
	КонецЕсли;
	Если Области.Количество() = ИндексОбласти + 1 Тогда
		ИндексСледующейОбласти = Неопределено;
		ИндексУзлаСледующейОбласти = Неопределено;
	Иначе
		ИндексСледующейОбласти = ИндексОбласти + 1;
		ИндексУзлаСледующейОбласти = Области[ИндексСледующейОбласти].Индекс;
	КонецЕсли;
	
	
	ДеревоОбласти = ДеревоДокумента();
	Для Каждого Узел Из КоллекцияПеребора Цикл
		Если Узел.Индекс < ИндексУзлаТекущейОбласти Тогда
			Продолжить;
		КонецЕсли;
		 
		Если ИндексУзлаСледующейОбласти <> Неопределено И Узел.Индекс >= ИндексУзлаСледующейОбласти Тогда
			Прервать;
		КонецЕсли;
		
		НовыйУзел = СкопироватьУзел(ДеревоОбласти, ДеревоОбласти.Строки.Количество(), Узел);
		СоздатьПоследующие(НовыйУзел, Узел, ИндексУзлаСледующейОбласти);
	КонецЦикла;
	
	ВосстановитьПолныйТекст(ДеревоОбласти, Гиперссылки);
	
	МассивПараметров = Новый Массив;
	Для Каждого СтрокаДерева Из ДеревоОбласти.Строки Цикл
		ОбщегоНазначенияКлиентСервер.ДополнитьМассив(МассивПараметров, УправлениеПечатью.НайтиПараметрыВТексте(СтрокаДерева.ПолныйТекст));
	КонецЦикла;
	
	МассивУзловГиперссылок = Новый Массив;
	НайтиУзлыПоСодержимому(ДеревоОбласти, "w:hyperlink", МассивУзловГиперссылок);
	
	Для Каждого УзелГиперссылки Из МассивУзловГиперссылок Цикл 
		ТекстГиперссылки = Гиперссылки[УзелГиперссылки.Атрибуты["r:id"]];
		ОбщегоНазначенияКлиентСервер.ДополнитьМассив(МассивПараметров, УправлениеПечатью.НайтиПараметрыВТексте(ТекстГиперссылки));
	КонецЦикла;
	
	Результат = Новый Структура("ДеревоОбласти, Параметры");
	Результат.ДеревоОбласти = ДеревоОбласти;
	Результат.Параметры = МассивПараметров;
	
	Возврат Результат;
КонецФункции

// Параметры:
//  СтрокаДерева - СтрокаДереваЗначений из см. ДеревоДокумента
//  Ключ - Строка
//  МассивУзлов - Массив из см. ДеревоДокумента
//
Функция НайтиУзлы(СтрокаДерева, Ключ, МассивУзлов) Экспорт
	НайденыУзлы = Ложь;
	Для Каждого Строка Из СтрокаДерева.Строки Цикл
		КоличествоНайденныхУзлов = МассивУзлов.ВГраница();
		
		КоличествоВхождений = СтрЧислоВхождений(Строка.ПолныйТекст, Ключ);
		
		Если КоличествоВхождений И Не НайтиУзлы(Строка, Ключ, МассивУзлов) Тогда
			Если КоличествоНайденныхУзлов = МассивУзлов.ВГраница() Тогда
				КоличествоВхождений = КоличествоВхождений - 1;
				МассивУзлов.Добавить(Строка);
				НайденыУзлы = Истина;
			КонецЕсли;
		КонецЕсли;
		
	КонецЦикла;
	Возврат НайденыУзлы;
КонецФункции

Функция МассивВСоответствие(Массив)
	Соответствие = Новый Соответствие();
	Для Каждого Элемент Из Массив Цикл
		Соответствие.Вставить(Элемент, Истина);
	КонецЦикла; 
	Возврат Соответствие;
КонецФункции 

// Осуществляет поиск первого узла, в дереве или строке значений.
// 
// Параметры:
//  СтрокаДерева - см. ДеревоДокумента
//  ИмяТега - Строка - имя тега
//  МассивУзлов - см. ДеревоДокумента
//  ИмяАтрибута - Неопределено, Строка - имя атрибута
//  ЗначенияАтрибута - Неопределено, Строка, Массив, Произвольный - значения атрибута
// 
// Возвращаемое значение:
//   см. ДеревоДокумента
//  
Функция НайтиУзелПоСодержимому(СтрокаДерева, ИмяТега, ИмяАтрибута = Неопределено, Знач ЗначенияАтрибута = Неопределено) Экспорт
	МассивУзлов = Новый Массив;
	ПараметрыПоискаУзлов = ПараметрыПоискаУзлов();
	ПараметрыПоискаУзлов.ИмяАтрибута = ИмяАтрибута;
	ПараметрыПоискаУзлов.ЗначенияАтрибута = ЗначенияАтрибута;
	ПараметрыПоискаУзлов.ПервоеЗначение = Истина;	
	НайтиУзлыПоСодержимому(СтрокаДерева, ИмяТега, МассивУзлов, ПараметрыПоискаУзлов);
	Если МассивУзлов.Количество() = 1 Тогда
		Возврат МассивУзлов[0];
	Иначе
		Возврат Неопределено;
	КонецЕсли;	
КонецФункции

// Параметры поиска узлов.
// 
// Возвращаемое значение:
//  Структура:
//   * ИмяАтрибута - Неопределено
//   * ЗначенияАтрибута - Неопределено
//   * ПервоеЗначение - Булево
//   * ТолькоПодчиненные - Булево
//
Функция ПараметрыПоискаУзлов() Экспорт
	СтруктураПараметров = Новый Структура;
	СтруктураПараметров.Вставить("ИмяАтрибута", Неопределено);
	СтруктураПараметров.Вставить("ЗначенияАтрибута", Неопределено);
	СтруктураПараметров.Вставить("ПервоеЗначение", Ложь);
	СтруктураПараметров.Вставить("ВключатьПодчиненные", Истина);
	Возврат СтруктураПараметров;
КонецФункции

// Осуществляет поиск узлов, в дереве или строке значений.
// 
// Параметры:
//  СтрокаДерева - см. ДеревоДокумента
//  ИмяТега - Строка - имя тега
//  МассивУзлов - см. ДеревоДокумента
//  ПараметрыПоиска - см. ПараметрыПоискаУзлов
//
Процедура НайтиУзлыПоСодержимому(СтрокаДерева, ИмяТега, МассивУзлов, ПараметрыПоиска = Неопределено) Экспорт
	Если ПараметрыПоиска = Неопределено Тогда
		ПараметрыПоиска = ПараметрыПоискаУзлов();
	КонецЕсли;
	ИмяАтрибута = ПараметрыПоиска.ИмяАтрибута;
	ЗначенияАтрибута = ПараметрыПоиска.ЗначенияАтрибута;
	ПервоеЗначение = ПараметрыПоиска.ПервоеЗначение;
	ВключатьПодчиненные = ПараметрыПоиска.ВключатьПодчиненные;
	
	Если ТипЗнч(ЗначенияАтрибута) = Тип("Строка") Тогда
		ЗначенияАтрибута = СтрРазделить(ЗначенияАтрибута, ",", Ложь);
		ЗначенияАтрибута = МассивВСоответствие(ЗначенияАтрибута);
	ИначеЕсли ТипЗнч(ЗначенияАтрибута) = Тип("Массив") Тогда
		ЗначенияАтрибута = МассивВСоответствие(ЗначенияАтрибута);
	КонецЕсли;
	
	
	ОтборПоТегу = Новый Структура("ИмяТега", ИмяТега);
	
	СтрокиПоТегу = СтрокаДерева.Строки.НайтиСтроки(ОтборПоТегу, ВключатьПодчиненные);
	
	Для Каждого Строка Из СтрокиПоТегу Цикл
		Если ИмяАтрибута <> Неопределено Тогда
			ТекущиеАтрибуты = Строка.Атрибуты;
			ТекущееЗначениеАтрибута = ТекущиеАтрибуты.Получить(ИмяАтрибута);
			Если ТекущееЗначениеАтрибута = Неопределено Тогда
				Продолжить;
			КонецЕсли;
				
			Если ЗначенияАтрибута <> Неопределено Тогда
				Если ЗначенияАтрибута.Получить(ТекущееЗначениеАтрибута) = Неопределено Тогда
					Продолжить;
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
		МассивУзлов.Добавить(Строка);
		Если ПервоеЗначение Тогда
			Возврат;
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры


Процедура ВосстановитьПолныйТекст(ДеревоXML, Гиперссылки) Экспорт
	Для Каждого Строка Из ДеревоXML.Строки Цикл
		ВосстановитьПолныйТекстРекурсивно(Строка, Гиперссылки);
	КонецЦикла;
КонецПроцедуры

Процедура ВосстановитьПолныйТекстРекурсивно(СтрокаДерева, Гиперссылки)
	
	СтрокаДерева.ПолныйТекст = "";
	
	Если Не СтрокаДерева.Строки.Количество() Тогда
		СтрокаДерева.ПолныйТекст = СтрокаДерева.Текст;
		Если Гиперссылки <> Неопределено И СтрокаДерева.ИмяТега = "w:hyperlink" Тогда
			ТекстСсылки = Гиперссылки[СтрокаДерева.Атрибуты["r:id"]];
			Если ТекстСсылки <> Неопределено Тогда
				СтрокаДерева.ПолныйТекст = ТекстСсылки + СтрокаДерева.ПолныйТекст;
			КонецЕсли;
		КонецЕсли;
	Иначе
		Для Каждого ПодСтрока Из СтрокаДерева.Строки Цикл
			ВосстановитьПолныйТекстРекурсивно(ПодСтрока, Гиперссылки);
			СтрокаДерева.ПолныйТекст = СтрокаДерева.ПолныйТекст + ПодСтрока.ПолныйТекст;
			Если Гиперссылки <> Неопределено И СтрокаДерева.ИмяТега = "w:hyperlink" Тогда
				ТекстСсылки = Гиперссылки[СтрокаДерева.Атрибуты["r:id"]];
				Если ТекстСсылки <> Неопределено Тогда
					СтрокаДерева.ПолныйТекст = ТекстСсылки + СтрокаДерева.ПолныйТекст;
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
КонецПроцедуры

// Возвращаемое значение:
// - СтрокаДереваЗначений из см. ДеревоДокумента
// - Неопределено
//
Функция НайтиУзел(Узел, Направление, Имя)
	
	КоллекцияСтрокУзла = Узел.Строки;
		
	КоличествоСтрок = КоллекцияСтрокУзла.Количество() - 1;
	
	Если Направление < 0 Тогда
		Для к = 0 По КоличествоСтрок Цикл
			СтрокаПоиска = КоллекцияСтрокУзла.Получить(КоличествоСтрок-к);
			Если СтрокаПоиска.ИмяТега = Имя Тогда
				Возврат СтрокаПоиска;
			КонецЕсли;
		КонецЦикла;
	Иначе
		Для к = 0 По КоличествоСтрок Цикл
			СтрокаПоиска = КоллекцияСтрокУзла.Получить(к);
			Если СтрокаПоиска.ИмяТега = Имя Тогда
				Возврат СтрокаПоиска;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Возврат Неопределено;
КонецФункции

Функция НайтиУзелРодитель(Узел, Имя)
	Родитель = Узел.Родитель;
	Если Родитель = Неопределено Тогда
		Возврат Неопределено;
	ИначеЕсли Родитель.ИмяТега = Имя Тогда
		Возврат Родитель;
	Иначе
		Возврат НайтиУзелРодитель(Родитель, Имя);
	КонецЕсли;
КонецФункции

// Скопировать узел.
// 
// Параметры:
//  УзелРодителя - СтрокаДереваЗначений:
//   * ИмяТега - Строка
//   * Текст - Строка
//   * ПолныйТекст - Строка
//   * Атрибуты - Соответствие
//  Индекс - Число - индекс
//  Узел - Неопределено, СтрокаДереваЗначений:
//   * ИмяТега - Строка
//   * Текст - Строка
//   * ПолныйТекст - Строка
//   * Атрибуты - Соответствие
// 
// Возвращаемое значение:
//  СтрокаДереваЗначений:
//   * ИмяТега - Строка
//   * Текст - Строка
//   * ПолныйТекст - Строка
//   * Атрибуты - Соответствие
//
Функция СкопироватьУзел(УзелРодителя, Индекс, Узел) Экспорт
	Если УзелРодителя.Строки.Количество() <= Индекс Тогда
		УзелКлона = УзелРодителя.Строки.Добавить();
	Иначе
		УзелКлона = УзелРодителя.Строки.Вставить(Индекс);
	КонецЕсли;
	ЗаполнитьЗначенияСвойств(УзелКлона, Узел, "ИмяТега,Текст,ПолныйТекст,Индекс");
	УзелКлона.Атрибуты = Новый Соответствие;
	ОбщегоНазначенияКлиентСервер.ДополнитьСоответствие(УзелКлона.Атрибуты, Узел.Атрибуты);
		
	Возврат УзелКлона;
КонецФункции

// Создает копии подчиненных узлов, в узле приемнике. 
// 
// Параметры:
//  Приемник - см. УправлениеПечатьюСлужебный.ПрочитатьXMLВДерево
//  Источник - см. УправлениеПечатьюСлужебный.ПрочитатьXMLВДерево
//
Процедура СоздатьПоследующие(НоваяСтрока, ТекущаяСтрока, НижнийИндекс = Неопределено) Экспорт
	
	Для Каждого ТСтрока Из ТекущаяСтрока.Строки Цикл
		Если НижнийИндекс <> Неопределено И НижнийИндекс <= ТСтрока.Индекс Тогда
			Прервать;
		КонецЕсли;
		НСтрока = СкопироватьУзел(НоваяСтрока, НоваяСтрока.Строки.Количество(), ТСтрока);
		СоздатьПоследующие(НСтрока, ТСтрока, НижнийИндекс);						
	КонецЦикла;	
	
КонецПроцедуры

Процедура ПолучитьОбластиИзДерева(УказательДерева, Области, ИменаТабличныхЧастей, КонецОбласти = Ложь)
	Для Каждого Строка Из УказательДерева.Строки Цикл
		Если СтрокаСодержитНачалоОбласти(Строка.ПолныйТекст, ИменаТабличныхЧастей) Тогда
			
			ЭтоКонецОбласти = СтрНайти(Строка.ПолныйТекст, "{/"+ИмяТегаУсловие()) <> 0;
			Если Не Строка.Строки.Количество() Тогда
				ДобавитьУзелОбласти(Области, Строка, ЭтоКонецОбласти, ИменаТабличныхЧастей); 
			Иначе			
				ПолучитьОбластиИзДерева(Строка, Области, ИменаТабличныхЧастей, ЭтоКонецОбласти);
			КонецЕсли;
			
			// Поиск условий области
			КрайняяОбласть = Области[Области.Количество()-1];
			Если КрайняяОбласть <> Неопределено И СтрНайти(Строка.ПолныйТекст, "{"+ИмяТегаУсловие()) И СтрНайти(Строка.ПолныйТекст, "}") И КрайняяОбласть.УсловиеОбласти = Неопределено Тогда
				МассивУсловияНачало = СтрРазделить(Строка.ПолныйТекст, "{", Ложь);
				Для к=0 По МассивУсловияНачало.ВГраница() Цикл
					Если СтрНайти(МассивУсловияНачало[к], ИмяТегаУсловие()+" ") Тогда
						МассивУсловияОкончания = СтрРазделить(МассивУсловияНачало[к], "}", Ложь);
						КрайняяОбласть.УсловиеОбласти = СокрЛП(СтрЗаменить(МассивУсловияОкончания[0], ИмяТегаУсловие()+" ", ""));
						Прервать;
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
		ИначеЕсли СтрНайти(Строка.ПолныйТекст, "{") И Не Строка.Строки.Количество() Тогда
			ДобавитьУзелОбласти(Области, Строка, КонецОбласти, ИменаТабличныхЧастей); 
		ИначеЕсли СтрНайти(Строка.ПолныйТекст, "{") Тогда
			ПолучитьОбластиИзДерева(Строка, Области, ИменаТабличныхЧастей, ЭтоКонецОбласти);
		КонецЕсли;			 		
	КонецЦикла;
	
КонецПроцедуры

Процедура ДобавитьУзелОбласти(Области, Строка, ЭтоКонецОбласти, ИменаТабличныхЧастей)
	
	Если СтрокаСодержитНачалоТабличнойЧасти(Строка.ПолныйТекст, ИменаТабличныхЧастей, Ложь) Тогда
		УзелДереваДокумента = НайтиКореньТабличнойОбласти(Строка);
		Если Области.Найти(УзелДереваДокумента, "УзелДереваДокумента") = Неопределено Тогда
			НоваяОбласть = Области.Добавить();
			НоваяОбласть.УзелДереваДокумента = УзелДереваДокумента;
			НоваяОбласть.УсловиеОбласти = Неопределено;
			
			Для каждого ИмяТабличнойЧасти Из ИменаТабличныхЧастей Цикл
				Если СтрНайти(Строка.ПолныйТекст, "["+ИмяТабличнойЧасти+".") Тогда
					Прервать;
				КонецЕсли;  			
			КонецЦикла;
			НоваяОбласть.Коллекция = ИмяТабличнойЧасти;
			
		КонецЕсли;
	Иначе
		НоваяОбласть = Области.Добавить();
		НоваяОбласть.УзелДереваДокумента = Строка;
		НоваяОбласть.УсловиеОбласти = Неопределено;
	КонецЕсли;
КонецПроцедуры

Функция НайтиКореньТабличнойОбласти(Строка)
	Указатель = Строка;
	
	СтруктураРодителей = Новый Структура("Абзац, СтрокаТаблицы");
	
	Пока ЗначениеЗаполнено(Указатель.Родитель) Цикл
		Указатель = Указатель.Родитель;
		Если Указатель.имяТега = "w:tr" И НЕ ЗначениеЗаполнено(СтруктураРодителей.СтрокаТаблицы) Тогда
			СтруктураРодителей.СтрокаТаблицы = Указатель;
		ИначеЕсли Указатель.имяТега = "w:p" И НЕ ЗначениеЗаполнено(СтруктураРодителей.Абзац) Тогда
			СтруктураРодителей.Абзац = Указатель;
		КонецЕсли; 
	КонецЦикла;
	
	Возврат ?(ЗначениеЗаполнено(СтруктураРодителей.СтрокаТаблицы), СтруктураРодителей.СтрокаТаблицы, СтруктураРодителей.Абзац);
	 
КонецФункции

Функция ПолучитьСледующийУзел(Узел)
	УзелРодитель = Узел.Родитель;
	Индекс = УзелРодитель.Строки.Индекс(Узел);
	Если Индекс + 1 = УзелРодитель.Строки.Количество() Тогда
		Возврат ПолучитьСледующийУзел(УзелРодитель);
	Иначе 
		Возврат УзелРодитель.Строки[Индекс+1];
	КонецЕсли;
КонецФункции

Функция ГраницаСледующейОбласти(Строка, Области)
	Родитель = Строка.Родитель;
	Если Родитель = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	ИндексСледующегоУзла = Родитель.Строки.Индекс(Строка)+1;
	ПерейтиКРодителю = Ложь;
	Если ИндексСледующегоУзла = Родитель.Строки.Количество() Тогда
		ПерейтиКРодителю = Истина;
	Иначе
		Для ИндексСтроки = Родитель.Строки.Индекс(Строка)+1 По Родитель.Строки.Количество()-1 Цикл
			ПерейтиКРодителю = Родитель.Строки[ИндексСтроки].ПолныйТекст = "";
			Если Не ПерейтиКРодителю Тогда
				Прервать;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
		
	Если ПерейтиКРодителю Тогда
		
		Возврат ГраницаСледующейОбласти(Родитель, Области);
		
	Иначе
		
		УзелНачалаОбласти = Родитель.Строки[ИндексСледующегоУзла];
		
		ЭтоНачалоТаблицы = УзелНачалаОбласти.ИмяТега = "w:tbl";
		Если ЭтоНачалоТаблицы Тогда
			ЕстьУзлыПредшественники = Родитель.Строки.Количество() > 2;
			Если ЕстьУзлыПредшественники Тогда
				УзелПредшественника = ТаблицаПредшественник(Родитель, ИндексСледующегоУзла-1);
				Если УзелПредшественника <> Неопределено Тогда
					СовместитьСеткуКолонок(УзелНачалаОбласти, УзелПредшественника);
					
					Пока Истина Цикл
						УзелДляСовмещения = ТаблицаПредшественник(Родитель, Родитель.Строки.Индекс(УзелПредшественника)-1);
						Если УзелДляСовмещения <> Неопределено Тогда
							СовместитьСеткуКолонок(УзелНачалаОбласти, УзелДляСовмещения);
						Иначе
							Прервать;
						КонецЕсли;
					КонецЦикла;
					
					СтрокиТаблицы = Новый Массив();
					НайтиУзлыПоСодержимому(УзелНачалаОбласти, "w:tr", СтрокиТаблицы);
					ПервыйДобавленныйУзел = Неопределено;
					Для Каждого СтрокаТаблицы Из СтрокиТаблицы Цикл
						НовыйУзел = СкопироватьУзел(УзелПредшественника, УзелПредшественника.Строки.Количество(), СтрокаТаблицы);
						СоздатьПоследующие(НовыйУзел, СтрокаТаблицы);
						ПервыйДобавленныйУзел = ?(ПервыйДобавленныйУзел = Неопределено, НовыйУзел, ПервыйДобавленныйУзел);
						
						ОбластьДляПодмены = Области.Найти(НовыйУзел.Индекс, "Индекс");
						Если ОбластьДляПодмены <> Неопределено Тогда 
							ОбластьДляПодмены.УзелДереваДокумента = НовыйУзел;
						КонецЕсли;
					КонецЦикла;
					
					Родитель.Строки.Удалить(УзелНачалаОбласти);
					Возврат ПервыйДобавленныйУзел;					
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
		
		Возврат Родитель.Строки[ИндексСледующегоУзла];
	КонецЕсли;
КонецФункции

Функция ТаблицаПредшественник(Родитель, ИндексТекущегоУзла)
	
	Для ИндексПоиска = 1 По ИндексТекущегоУзла Цикл
		УзелПредшественника = Родитель.Строки[ИндексТекущегоУзла-ИндексПоиска];
		Если УзелПредшественника.ИмяТега = "w:tbl" Тогда
			Возврат УзелПредшественника;
		ИначеЕсли УзелПредшественника.ИмяТега = "w:p" И СтрНачинаетсяС(УзелПредшественника.ПолныйТекст, "{"+ИмяТегаУсловие())
			И СтрЗаканчиваетсяНа(УзелПредшественника.ПолныйТекст, "}") Тогда
			Продолжить;
		КонецЕсли;
		Возврат Неопределено;
	КонецЦикла;
	Возврат Неопределено;

КонецФункции

Процедура СовместитьСеткуКолонок(УзелНачалаОбласти, УзелПредшественника)
	
	УзелСеткиСтолбцовПредшественника = НайтиУзелПоСодержимому(УзелПредшественника, "w:tblGrid");
	УзелСеткиСтолбцовДобавления = НайтиУзелПоСодержимому(УзелНачалаОбласти, "w:tblGrid");
	МассивСетки = Новый Массив;
	МассивСеткиПредшественника = Новый Массив;
	ТекущаяШирина = 0;
	Для Каждого УзелСетки Из УзелСеткиСтолбцовПредшественника.Строки Цикл
		ТекущаяШирина = ТекущаяШирина + Число(УзелСетки.Атрибуты["w:w"]);
		МассивСетки.Добавить(ТекущаяШирина);
		МассивСеткиПредшественника.Добавить(ТекущаяШирина);
	КонецЦикла;
	
	МассивСеткиДобавления = Новый Массив;
	ТекущаяШирина = 0;
	Для Каждого УзелСетки Из УзелСеткиСтолбцовДобавления.Строки Цикл
		ТекущаяШирина = ТекущаяШирина + Число(УзелСетки.Атрибуты["w:w"]);
		МассивСеткиДобавления.Добавить(ТекущаяШирина);
		ШиринаКлетокМассива = 0;
		Для ИндексСетки = 0 По МассивСетки.ВГраница() Цикл
			Если ТекущаяШирина = МассивСетки[ИндексСетки] Тогда
				Прервать;
			ИначеЕсли ТекущаяШирина > МассивСетки[ИндексСетки]
				И МассивСетки.ВГраница() = ИндексСетки Тогда
				МассивСетки.Добавить(ТекущаяШирина);
			ИначеЕсли (ТекущаяШирина > МассивСетки[ИндексСетки]
				И ТекущаяШирина < МассивСетки[ИндексСетки+1]) Тогда
				МассивСетки.Вставить(ИндексСетки+1, ТекущаяШирина);
				Прервать;
			КонецЕсли;
			ШиринаКлетокМассива = ШиринаКлетокМассива + МассивСетки[ИндексСетки];
		КонецЦикла;
	КонецЦикла;															
	
	МассивКоличестваКолонокПредшественника = ИспользованиеКолонок(УзелСеткиСтолбцовПредшественника, МассивСетки);
	МассивКоличестваКолонокДобавления = ИспользованиеКолонок(УзелСеткиСтолбцовДобавления, МассивСетки);
	
	УстановитьСетку(УзелПредшественника, МассивСетки);
	УстановитьСетку(УзелНачалаОбласти, МассивСетки);
	
	УстановитьИспользованиеСетки(УзелПредшественника, МассивКоличестваКолонокПредшественника);
	УстановитьИспользованиеСетки(УзелНачалаОбласти, МассивКоличестваКолонокДобавления);

КонецПроцедуры

Функция ИспользованиеКолонок(УзелСеткиСтолбцовПредшественника, МассивСетки)
	
	ИспользованиеКолонок = Новый Массив;
	ТекущаяШирина = 0;
	ИспользованоКолонокСетки = 0;
	НомерПредыдущейКолонки = 0;	
	Для Каждого УзелСетки Из УзелСеткиСтолбцовПредшественника.Строки Цикл
		ТекущаяШирина = ТекущаяШирина + Число(УзелСетки.Атрибуты["w:w"]);
		КоличествоКолонок = МассивСетки.Найти(ТекущаяШирина) - НомерПредыдущейКолонки + 1;
		НомерПредыдущейКолонки = МассивСетки.Найти(ТекущаяШирина)+1;
		ИспользованиеКолонок.Добавить(КоличествоКолонок);
		ИспользованоКолонокСетки = ИспользованоКолонокСетки + КоличествоКолонок;
	КонецЦикла;
	
	Если ИспользованоКолонокСетки < МассивСетки.Количество() Тогда
		ИспользованиеКолонок[ИспользованиеКолонок.ВГраница()] = ИспользованиеКолонок[ИспользованиеКолонок.ВГраница()]
			+ МассивСетки.Количество() - ИспользованоКолонокСетки;
	КонецЕсли;
	
	Возврат ИспользованиеКолонок;

КонецФункции

Процедура УстановитьСетку(УзелПредшественника, МассивСетки)
	
	УзелОпределенияСетки = НайтиУзелПоСодержимому(УзелПредшественника, "w:tblGrid");
	УзелОпределенияСетки.Строки.Очистить();
	ТекущаяШирина = 0;
	Для Каждого ЭлементСетки Из МассивСетки Цикл
		УзелОпределенияСеткиКолонки = УзелОпределенияСетки.Строки.Добавить();
		УзелОпределенияСеткиКолонки.ИмяТега = "w:gridCol";
		УзелОпределенияСеткиКолонки.Атрибуты.Вставить("w:w", Формат(ЭлементСетки-ТекущаяШирина, "ЧГ=;"));
		ТекущаяШирина = ЭлементСетки;
	КонецЦикла;

КонецПроцедуры

Процедура УстановитьИспользованиеСетки(Узел, Знач МассивКоличестваКолонок)
	МассивУзловСтрок = Новый Массив;
	ПараметрыПоиска = ПараметрыПоискаУзлов();
	ПараметрыПоиска.ВключатьПодчиненные = Ложь;
	НайтиУзлыПоСодержимому(Узел, "w:tr", МассивУзловСтрок, ПараметрыПоиска);
	
	Для Каждого УзелСтроки Из МассивУзловСтрок Цикл
		ПараметрыПоиска = ПараметрыПоискаУзлов();
		ПараметрыПоиска.ВключатьПодчиненные = Ложь;
		МассивУзловКолонок = Новый Массив;
		НайтиУзлыПоСодержимому(УзелСтроки, "w:tc", МассивУзловКолонок, ПараметрыПоиска);
		ИндексИспользованныхРанее = 0;
		Для ИндексКолонки = 0 По МассивУзловКолонок.ВГраница() Цикл
			УзелКолонки = МассивУзловКолонок[ИндексКолонки];
			УзелСвойствКолонки = НайтиУзелПоСодержимому(УзелКолонки, "w:tcPr");
			УзелОпределенияСетки = НайтиУзелПоСодержимому(УзелСвойствКолонки, "w:gridSpan");
			Если УзелОпределенияСетки = Неопределено Тогда
				УзелОпределенияСетки = УзелСвойствКолонки.Строки.Добавить();
				УзелОпределенияСетки.ИмяТега = "w:gridSpan";
				КоличествоКолонокСетки = МассивКоличестваКолонок[ИндексКолонки];
			Иначе
				КоличествоКолонокСетки = 0;
				РанееКоличествоКолонокСетки = Число("0"+УзелОпределенияСетки.Атрибуты["w:val"]);
				Для ИндексИспользованныхВСтаройСетке = ИндексИспользованныхРанее По ИндексИспользованныхРанее + РанееКоличествоКолонокСетки - 1 Цикл
					КоличествоКолонокСетки = КоличествоКолонокСетки + МассивКоличестваКолонок[ИндексИспользованныхВСтаройСетке];
				КонецЦикла;
				ИндексИспользованныхРанее = ИндексИспользованныхВСтаройСетке;
			КонецЕсли;
			УзелОпределенияСетки.Атрибуты.Вставить("w:val", Формат(КоличествоКолонокСетки, "ЧГ=;"));
		КонецЦикла;
	КонецЦикла;
КонецПроцедуры

Функция ИмяТегаУсловие()
	Возврат УправлениеПечатьюКлиентСервер.ИмяТегаУсловие();
КонецФункции

Функция УсловиеОбласти(Область)
	МассивУсловияНачало = СтрРазделить(Область.ПолныйТекст, "{", Ложь);
	Для Индекс = 0 По МассивУсловияНачало.ВГраница() Цикл
		Если СтрНайти(МассивУсловияНачало[Индекс], ИмяТегаУсловие()+" ") Тогда
			МассивУсловияОкончания = СтрРазделить(МассивУсловияНачало[Индекс], "}", Ложь);
			Возврат СокрЛП(СтрЗаменить(МассивУсловияОкончания[0], ИмяТегаУсловие()+" ", ""));
		КонецЕсли;
	КонецЦикла;
	Возврат Неопределено;
КонецФункции

Функция СтрокаСодержитНачалоОбласти(Знач Текст, ИменаТабличныхЧастей)
	
	Результат = СтрНайти(Текст, "{"+ИмяТегаУсловие()+" ") ИЛИ СтрНайти(Текст, "{/"+ИмяТегаУсловие());
	СтрокаСодержитНачалоТабличнойЧасти(Текст, ИменаТабличныхЧастей, Результат);
	Возврат Результат;
	
КонецФункции

Функция СтрокаСодержитНачалоТабличнойЧасти(Текст, ИменаТабличныхЧастей, Результат)

	Если Не Результат Тогда
		Для каждого ИмяТабличнойЧасти Из ИменаТабличныхЧастей Цикл
			Результат = Результат ИЛИ СтрНайти(Текст, "["+ИмяТабличнойЧасти+".");
			Если Результат Тогда
				Прервать;
			КонецЕсли;  			
		КонецЦикла;
	КонецЕсли;
	
	Возврат Результат;
КонецФункции

Функция ПолучитьПечатнуюФорму(ДеревоМакета, АдресХранилища = Неопределено) Экспорт
	
	ПутьКДокументу = СобратьФайлОфисногоДокумента(ДеревоМакета);
	ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКДокументу);
	АдресХранилищаПечатнойФормы = ПоместитьВоВременноеХранилище(ДвоичныеДанные, 
		?(АдресХранилища = Неопределено, Новый УникальныйИдентификатор, АдресХранилища));
	
	УдалитьФайлы(ПутьКДокументу);
	УдалитьФайлы(ДеревоМакета.ИмяКаталога);
	
	Возврат АдресХранилищаПечатнойФормы;
КонецФункции

// Собрать файл офисного документа.
// 
// Параметры:
//  ДеревоМакета - см. УправлениеПечатьюСлужебный.ИнициализироватьДокументСКД.
//  Кодировка - Строка - кодировка
// 
// Возвращаемое значение:
//  Строка - путь к сформированному документу
//
Функция СобратьФайлОфисногоДокумента(ДеревоМакета, Кодировка = "UTF-8") Экспорт
	СтруктураДокумента = ДеревоМакета.СтруктураДокумента;
	Дерево = СтруктураДокумента.ДеревоДокумента;
	
	ИзменяемыеФайлы = Новый Соответствие;
	ИзменяемыеФайлы.Вставить("СвязиКонтента", ДеревоМакета.ИмяКаталога + УстановитьРазделительПути("\word\_rels\document.xml.rels"));
	ИзменяемыеФайлы.Вставить("ТипыКонтента",  ДеревоМакета.ИмяКаталога + УстановитьРазделительПути("\[Content_Types].xml"));
	ИзменяемыеФайлы.Вставить("Документ",      ДеревоМакета.ИмяКаталога + УстановитьРазделительПути("\word\document.xml"));
	
	
	ЗаписьXML = ИнициализироватьЗаписьXML("", ИзменяемыеФайлы.Получить("Документ"));
	ПоместитьДеревоВЗаписьXML(ЗаписьXML, Дерево);
	ЗаписьXML.Закрыть();
	
	МассивФайловКолонтитулов = Новый Массив;
	
	Для Каждого Колонтитул Из СтруктураДокумента.Колонтитулы Цикл
		ИмяФайла = ДеревоМакета.ИмяКаталога + УстановитьРазделительПути("\word\") + Колонтитул.Ключ + ".xml";
		Если Не Колонтитул.Значение.Строки.Количество() Тогда
			Продолжить;
		КонецЕсли;

		ЗаписьXML = Новый ЗаписьXML;
		ЗаписьXML = ИнициализироватьЗаписьXML("", ИмяФайла);
		Для каждого Подстрока Из Колонтитул.Значение.Строки Цикл
			ЗаписатьЭлемент(ЗаписьXML, Подстрока);	
		КонецЦикла;
		ЗаписьXML.Закрыть();
		
		МассивФайловКолонтитулов.Добавить(Колонтитул.Ключ);
	КонецЦикла;
	
	// Обрабатываем связи контента
	
	ЗаписьXML = ИнициализироватьЗаписьXML("", ИзменяемыеФайлы.Получить("СвязиКонтента"));
	ПоместитьДеревоВЗаписьXML(ЗаписьXML, СтруктураДокумента.СвязиКонтента);
	ЗаписьXML.Закрыть();
	
	// Обрабатываем типы контента
	
	ЗаписьXML = ИнициализироватьЗаписьXML("", ИзменяемыеФайлы.Получить("ТипыКонтента"));
	ПоместитьДеревоВЗаписьXML(ЗаписьXML, СтруктураДокумента.ТипыКонтента);
	ЗаписьXML.Закрыть();
	
	ПутьКДокументу = ПолучитьИмяВременногоФайла("DOCX");
	СобратьКонтейнерДокументаDOCX(ПутьКДокументу, ДеревоМакета.ИмяКаталога);
	Возврат ПутьКДокументу;
	
КонецФункции

Процедура ЗаписатьЭлемент(ЗаписьXML, СтрокаДерева)
	Если СтрокаДерева.Атрибуты["o:gfxdata"] <> Неопределено Тогда
		КонструкторТега = ИнициализироватьЗаписьXML("",,, Ложь);
		КонструкторТега.ЗаписатьНачалоЭлемента(СтрокаДерева.ИмяТега);
		Для Каждого Атрибут Из СтрокаДерева.Атрибуты Цикл
			КонструкторТега.ЗаписатьНачалоАтрибута(Атрибут.Ключ);
			Если Атрибут.Ключ = "o:gfxdata" Тогда
				КонструкторТега.ЗаписатьТекст("");
			Иначе
				КонструкторТега.ЗаписатьТекст(Атрибут.Значение);
			КонецЕсли;			
			КонструкторТега.ЗаписатьКонецАтрибута();	
		КонецЦикла;
		КонструкторТега.ЗаписатьКонецЭлемента();
		ПредставлениеТега = КонструкторТега.Закрыть();
		ПредставлениеАтрибута = "o:gfxdata="""+СтрЗаменить(СтрокаДерева.Атрибуты["o:gfxdata"], Символ(10), "&#xA;")+"""";
		ПредставлениеТега = СтрЗаменить(ПредставлениеТега, "o:gfxdata=""""", ПредставлениеАтрибута);
		ЗаписьXML.ЗаписатьБезОбработки(ПредставлениеТега);
	Иначе
		ЗаписьXML.ЗаписатьНачалоЭлемента(СтрокаДерева.ИмяТега);
		Для Каждого Атрибут Из СтрокаДерева.Атрибуты Цикл
			ЗаписьXML.ЗаписатьАтрибут(Атрибут.Ключ, Атрибут.Значение);
		КонецЦикла;
		
		Если СтрокаДерева.Текст <> "" Тогда
			ТекстЗаписи = СтрокаДерева.Текст;
			Если СтрНачинаетсяС(ТекстЗаписи, " HYPERLINK ") Тогда           
				МассивПоля = СтрРазделить(ТекстЗаписи, """");
				МассивПоля[1] = КодироватьСтроку(МассивПоля[1], СпособКодированияСтроки.КодировкаURL);
				ТекстЗаписи = СтрСоединить(МассивПоля,"""");
			КонецЕсли;
			ЗаписьXML.ЗаписатьТекст(ТекстЗаписи);
		КонецЕсли;
		
		Для каждого Подстрока Из СтрокаДерева.Строки Цикл
			ЗаписатьЭлемент(ЗаписьXML, Подстрока);	
		КонецЦикла;
	
		ЗаписьXML.ЗаписатьКонецЭлемента();
	КонецЕсли;
	
КонецПроцедуры

Процедура УстановитьЗначениеВДокумент(Узел, СоответствиеЗамены, ДеревоМакета, ДобавлятьСвязи) Экспорт
	СтруктураДокумента = ДеревоМакета.СтруктураДокумента;
	Если Узел.ИмяТега = "w:hyperlink" Тогда
		Гиперссылки = СтруктураДокумента.Гиперссылки;
		ТекстГиперссылки = Гиперссылки[Узел.Атрибуты["r:id"]];
		Если СтрНайти(ТекстГиперссылки, СоответствиеЗамены.Ключ) = 0 Тогда
			Возврат;
		КонецЕсли;
		ТекстГиперссылки = СтрЗаменить(ТекстГиперссылки, СоответствиеЗамены.Ключ, СоответствиеЗамены.Значение);
		Если ДобавлятьСвязи Тогда
			ИдРесурса = ДеревоМакета.СтруктураДокумента.МаксимальныйИдентификаторСвязи + 1;
			ДеревоМакета.СтруктураДокумента.МаксимальныйИдентификаторСвязи = ИдРесурса;
			ПолныйИдентификатор = "rId" + Формат(ИдРесурса, "ЧГ=0");
			Узел.Атрибуты["r:id"] = ПолныйИдентификатор;
			
	        Гиперссылки.Вставить(ПолныйИдентификатор, ТекстГиперссылки);
			УзелСвязей = ДеревоМакета.СтруктураДокумента.СвязиКонтента.Строки[0];
			УзелСвязейГиперссылки = УзелСвязей.Строки.Добавить();
			УзелСвязейГиперссылки.ИмяТега = "Relationship";
			УзелСвязейГиперссылки.Атрибуты.Вставить("Id", ПолныйИдентификатор); 
			УзелСвязейГиперссылки.Атрибуты.Вставить("Target", ТекстГиперссылки);
			УзелСвязейГиперссылки.Атрибуты.Вставить("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink");
			УзелСвязейГиперссылки.Атрибуты.Вставить("TargetMode", "External");
		Иначе
			ПолныйИдентификатор = Узел.Атрибуты["r:id"];
			МассивНайденныхУзлов = Новый Массив;
			ПараметрыПоиска = ПараметрыПоискаУзлов();
			ПараметрыПоиска.ИмяАтрибута = "Id";
			ПараметрыПоиска.ЗначенияАтрибута = ПолныйИдентификатор;
			НайтиУзлыПоСодержимому(ДеревоМакета.СтруктураДокумента.СвязиКонтента, "Relationship", МассивНайденныхУзлов, ПараметрыПоиска); 
			Если МассивНайденныхУзлов.Количество() <> 0 Тогда
				МассивНайденныхУзлов[0].Атрибуты.Вставить("Target", ТекстГиперссылки);	
				Гиперссылки.Вставить(ПолныйИдентификатор, ТекстГиперссылки);
			КонецЕсли;
		КонецЕсли;

	ИначеЕсли ДеревоМакета = Неопределено Или ТипЗнч(СоответствиеЗамены.Значение) <> Тип("Структура") Тогда
		Если СтрНайти(СоответствиеЗамены.Ключ, ".ШтампЭП") Тогда
			Узел.ИмяТега = "w:bookmarkStart";
			Узел.Текст = "";
			Узел.ПолныйТекст = "";
			Узел.Атрибуты.Очистить();
			Узел.Атрибуты.Вставить("w:id", "1");
			Узел.Атрибуты.Вставить("w:name", "V8DSStamp");
			Узел.Строки.Очистить();
				
			УзелОкончанияЗакладки = СкопироватьУзел(Узел.Родитель, Узел.Родитель.Строки.Индекс(Узел)+1, Узел);
			УзелОкончанияЗакладки.ИмяТега = "w:bookmarkEnd";
			УзелОкончанияЗакладки.Атрибуты.Удалить("w:name");
		Иначе
			СтрокиЗначения = СтрРазделить(СоответствиеЗамены.Значение, Символы.ПС, Истина);
			СтрокиТекста = Новый Массив;
			ТекстУзла = Узел.Текст;
			ДлиннаКлюча = СтрДлина(СоответствиеЗамены.Ключ);
			ПозицияВхождения = СтрНайти(ТекстУзла, СоответствиеЗамены.Ключ);
			Пока ПозицияВхождения <> 0 Цикл
				Если ПозицияВхождения > 1 Тогда
					СтрокиТекста.Добавить(Лев(ТекстУзла, ПозицияВхождения-1));
				КонецЕсли;
				
				СтрокиТекста.Добавить(СоответствиеЗамены.Ключ);
				ТекстУзла = Сред(ТекстУзла, ПозицияВхождения + ДлиннаКлюча);
				ПозицияВхождения = СтрНайти(ТекстУзла, СоответствиеЗамены.Ключ);
			КонецЦикла;
			
			Если СтрДлина(ТекстУзла) > 0 Тогда
				СтрокиТекста.Добавить(ТекстУзла);
			КонецЕсли;
			Узел.Текст = "";
			РодительУзла = Узел.Родитель;
			
			Для Каждого СтрокаТекста Из СтрокиТекста Цикл
				Если СтрокаТекста = СоответствиеЗамены.Ключ Тогда
					Для ИндексСтрокиЗначения = 0 По СтрокиЗначения.ВГраница() Цикл
						СтрокаЗначения = СтрокиЗначения[ИндексСтрокиЗначения];
						Если ИндексСтрокиЗначения = 0 Тогда
							Узел.Текст = Узел.Текст + СтрокаЗначения;
						Иначе
							УзелПереводаСтроки = РодительУзла.Строки.Вставить(РодительУзла.Строки.Индекс(Узел)+1);
							УзелПереводаСтроки.Индекс = Узел.Индекс + (1 - Узел.Индекс + Цел(Узел.Индекс))/2; 
							УзелПереводаСтроки.ИмяТега = "w:br";
							
							Узел = СкопироватьУзел(РодительУзла, РодительУзла.Строки.Индекс(Узел)+2, Узел);
							Узел.Индекс = УзелПереводаСтроки.Индекс + (1 - УзелПереводаСтроки.Индекс + Цел(УзелПереводаСтроки.Индекс))/2;
							Узел.Текст = СтрокаЗначения;
						КонецЕсли;
					КонецЦикла;
				Иначе
					Узел.Текст = Узел.Текст + СтрокаТекста;
				КонецЕсли;
			КонецЦикла;
			
		КонецЕсли;
		
	Иначе
		СтруктураЗначения = СоответствиеЗамены.Значение;
		
		Если Не ЭтоАдресВременногоХранилища(СтруктураЗначения.АдресКартинки) Тогда
			Узел.Текст = "";
			Возврат;
		КонецЕсли;
			
		ДвоичныеДанные = ПолучитьИзВременногоХранилища(СтруктураЗначения.АдресКартинки); // ДвоичныеДанные - 
				
		СтруктураКартинка = Новый Структура;
		СтруктураКартинка.Вставить("ДвоичныеДанные",     ДвоичныеДанные);
		СтруктураКартинка.Вставить("ИмяКартинки",        "image");
				
		ПараметрыКартинки = ПолучитьАтрибутыИзображения(ДвоичныеДанные);
				
		Если ПараметрыКартинки.Количество() = 0 ИЛИ ПараметрыКартинки.ТипИзображения = Null Тогда
			Узел.Текст = "";
			Возврат;
		КонецЕсли;
		
		РазмерыКартинки = Новый Структура("Ширина,Высота",0,0);
		ЗаполнитьЗначенияСвойств(РазмерыКартинки, СтруктураЗначения);
		
		РазрешениеОсновногоЭкрана = СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере().Получить("РазрешениеОсновногоЭкрана");
		РазрешениеОсновногоЭкрана = ?(РазрешениеОсновногоЭкрана = Неопределено, 72, РазрешениеОсновногоЭкрана);

		УзелДляПоиска = ДеревоМакета.СтруктураДокумента.ДеревоДокумента.Строки.Найти(Узел.Индекс, "Индекс", Истина);
		УзелТаблицы = НайтиУзелРодитель(УзелДляПоиска, "w:tbl");
		Если УзелТаблицы = Неопределено Тогда
			ШиринаКлеткиТаблицы = 0;
		Иначе
			
			УзелОписанияШириныТаблицы = НайтиУзелПоСодержимому(УзелТаблицы, "w:tblW");
			
			ТипDXA = Ложь;
			ТипPCT = Ложь;
			
			ШиринаТаблицы    = УзелОписанияШириныТаблицы.Атрибуты["w:w"];
			ТипШирины = УзелОписанияШириныТаблицы.Атрибуты["w:type"];   
			
			УзелЯчейки = НайтиУзелРодитель(УзелДляПоиска, "w:tc");
			УзелОписанияШириныЯчейки = НайтиУзелПоСодержимому(УзелЯчейки, "w:tcW");
			ШиринаКлеткиТаблицы = УзелОписанияШириныЯчейки.Атрибуты["w:w"];
			
			Если ТипШирины = "auto" Тогда
				ТипDXA = Ложь;
			ИначеЕсли ТипШирины = "dxa" Тогда
				ТипDXA = Истина;
			ИначеЕсли ТипШирины = "pct" Тогда
				ТипPCT = Истина;
			КонецЕсли;
			
			Если НЕ ТипDXA ИЛИ (ТипPCT И ШиринаТаблицы = 0) Тогда
				ШиринаКлеткиТаблицы = 0;
			ИначеЕсли ТипPCT И НЕ ШиринаТаблицы = 0 Тогда
				
				// 5000 - значение равное 100% для типа "pct".
				// ПолеРодитель - в значениях dxa.
				
				ШиринаКлеткиТаблицы = ШиринаТаблицы * ШиринаКлеткиТаблицы / 50 / 100;
				
			КонецЕсли;
		КонецЕсли;
					
		Если НЕ ШиринаКлеткиТаблицы = 0 Тогда
			
			ОтношениеВысотыКШирине = ПараметрыКартинки.Высота / ПараметрыКартинки.Ширина;
			
			ШиринаКартинки = ШиринаКлеткиТаблицы * 914400 / РазрешениеОсновногоЭкрана / 20;
			ВысотаКартинки = ОтношениеВысотыКШирине * ШиринаКлеткиТаблицы * 914400 / РазрешениеОсновногоЭкрана / 20;
			
		Иначе
			
			Если ЗначениеЗаполнено(РазмерыКартинки.Высота) ИЛИ ЗначениеЗаполнено(РазмерыКартинки.Ширина) Тогда
				
				КоэффициентПересчета = 914400/2.54/10;
				Если РазмерыКартинки.Ширина <> 0 Тогда 
					ШиринаКартинки = КоэффициентПересчета * РазмерыКартинки.Ширина;
					КоэффициентМасштабирования = ШиринаКартинки/ПараметрыКартинки.Ширина;
				КонецЕсли;
				
				Если РазмерыКартинки.Высота <> 0 Тогда 
					ВысотаКартинки = КоэффициентПересчета * РазмерыКартинки.Высота;
					КоэффициентМасштабирования = ВысотаКартинки/ПараметрыКартинки.Высота;
				КонецЕсли;
				
				Если РазмерыКартинки.Ширина = 0 Тогда
					ШиринаКартинки = КоэффициентМасштабирования*ПараметрыКартинки.Ширина;
				КонецЕсли;
				
				Если РазмерыКартинки.Высота = 0 Тогда
					ВысотаКартинки = КоэффициентМасштабирования*ПараметрыКартинки.Высота;
				КонецЕсли;
				
			Иначе
				КоэффициентМасштаба = 2;
				КоэффициентПропорций = 914400 / (РазрешениеОсновногоЭкрана * КоэффициентМасштаба);
				
				ШиринаКартинки = КоэффициентПропорций * ПараметрыКартинки.Ширина;
				ВысотаКартинки = КоэффициентПропорций * ПараметрыКартинки.Высота;
			КонецЕсли;
		КонецЕсли;
		
		ШиринаКартинки = Окр(ШиринаКартинки, 0);
		ВысотаКартинки = Окр(ВысотаКартинки, 0);
		
		СтруктураКартинка.Вставить("РасширениеКартинки", СтрЗаменить(ПараметрыКартинки.ТипИзображения, "image/", ""));
		СтруктураКартинка.Вставить("ШиринаКартинки",     ШиринаКартинки);
		СтруктураКартинка.Вставить("ВысотаКартинки",     ВысотаКартинки);
		
		
		ВнестиКартинкуВБиблиотекуДокументаСКД(ДеревоМакета, СтруктураКартинка);
		ШаблонКартинкиXML = ПолучитьШаблонКартинки();
		ПодготовитьШаблонКЧтениюXML(ШаблонКартинкиXML);
		ПодготовитьШаблонКартинки(ШаблонКартинкиXML, СтруктураКартинка);
		ДеревоКартинки = ПрочитатьСтрокуXMLВДерево(СтруктураКартинка.ТекстКартинки);
		
		УзелДокументаКартинки = ДеревоКартинки.Строки[0];
		ИндексРазмещения = Узел.Родитель.Строки.Индекс(Узел);
		
		МассивЧастейТекста = СтрРазделить(СтрЗаменить(Узел.Текст, СоответствиеЗамены.Ключ, Символы.ПС), Символы.ПС);
		Для СчетчикЧастей = 0 По МассивЧастейТекста.ВГраница() Цикл
			ЧастьТекста = МассивЧастейТекста[СчетчикЧастей];
			Если ЧастьТекста <> "" Тогда
				ДобавляемыйУзел = СкопироватьУзел(Узел.Родитель, ИндексРазмещения, Узел);
				ДобавляемыйУзел.Текст = ЧастьТекста;
				ИндексРазмещения = ИндексРазмещения + 1;
			КонецЕсли;
			
			Если СчетчикЧастей < МассивЧастейТекста.ВГраница() Тогда
				Для Каждого УзелКартинки Из УзелДокументаКартинки.Строки Цикл
			   		ДобавляемыйУзел = СкопироватьУзел(Узел.Родитель, ИндексРазмещения+1, УзелКартинки);
					СоздатьПоследующие(ДобавляемыйУзел, УзелКартинки);
					ИндексРазмещения = ИндексРазмещения + 1;
				КонецЦикла;
			КонецЕсли;
		КонецЦикла;
		Узел.Родитель.Строки.Удалить(Узел);
		
	КонецЕсли;

КонецПроцедуры

Процедура ПодготовитьШаблонКЧтениюXML(ШаблонКартинкиXML)
	ШаблонКартинкиXML = "<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>
		|<w:document xmlns:wpc=""http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"" xmlns:cx=""http://schemas.microsoft.com/office/drawing/2014/chartex"" xmlns:cx1=""http://schemas.microsoft.com/office/drawing/2015/9/8/chartex"" xmlns:cx2=""http://schemas.microsoft.com/office/drawing/2015/10/21/chartex"" xmlns:cx3=""http://schemas.microsoft.com/office/drawing/2016/5/9/chartex"" xmlns:cx4=""http://schemas.microsoft.com/office/drawing/2016/5/10/chartex"" xmlns:cx5=""http://schemas.microsoft.com/office/drawing/2016/5/11/chartex"" xmlns:cx6=""http://schemas.microsoft.com/office/drawing/2016/5/12/chartex"" xmlns:cx7=""http://schemas.microsoft.com/office/drawing/2016/5/13/chartex"" xmlns:cx8=""http://schemas.microsoft.com/office/drawing/2016/5/14/chartex"" xmlns:mc=""http://schemas.openxmlformats.org/markup-compatibility/2006"" xmlns:aink=""http://schemas.microsoft.com/office/drawing/2016/ink"" xmlns:am3d=""http://schemas.microsoft.com/office/drawing/2017/model3d"" xmlns:o=""urn:schemas-microsoft-com:office:office"" xmlns:r=""http://schemas.openxmlformats.org/officeDocument/2006/relationships"" xmlns:m=""http://schemas.openxmlformats.org/officeDocument/2006/math"" xmlns:v=""urn:schemas-microsoft-com:vml"" xmlns:wp14=""http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"" xmlns:wp=""http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"" xmlns:w10=""urn:schemas-microsoft-com:office:word"" xmlns:w=""http://schemas.openxmlformats.org/wordprocessingml/2006/main"" xmlns:w14=""http://schemas.microsoft.com/office/word/2010/wordml"" xmlns:w15=""http://schemas.microsoft.com/office/word/2012/wordml"" xmlns:w16cid=""http://schemas.microsoft.com/office/word/2016/wordml/cid"" xmlns:w16se=""http://schemas.microsoft.com/office/word/2015/wordml/symex"" xmlns:wpg=""http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"" xmlns:wpi=""http://schemas.microsoft.com/office/word/2010/wordprocessingInk"" xmlns:wne=""http://schemas.microsoft.com/office/word/2006/wordml"" xmlns:wps=""http://schemas.microsoft.com/office/word/2010/wordprocessingShape"" mc:Ignorable=""w14 w15 w16se w16cid wp14"">"
		+ ШаблонКартинкиXML 
		+"</w:document>";
КонецПроцедуры

Процедура ВнестиКартинкуВБиблиотекуДокументаСКД(ДеревоМакета, СтруктураКартинка)
	
	КаталогКартинок = ДеревоМакета.СтруктураДокумента.КаталогКартинок;
	
	КаталогMedia = Новый Файл(КаталогКартинок);
	ТипКартинка = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
	
	Если НЕ КаталогMedia.Существует() Тогда
		СоздатьКаталог(КаталогКартинок);
	КонецЕсли;
	
	УзелСвязей = ДеревоМакета.СтруктураДокумента.СвязиКонтента.Строки[0];
	РасширениеКартинки = СтруктураКартинка.РасширениеКартинки;
	
	ИдРесурса = ДеревоМакета.СтруктураДокумента.МаксимальныйИдентификаторСвязи + 1;
	УзелСвязейКартинки = УзелСвязей.Строки.Добавить();
	УзелСвязейКартинки.ИмяТега = "Relationship";
	УзелСвязейКартинки.Атрибуты.Вставить("Id", "rId" + Формат(ИдРесурса, "ЧГ=0"));
	ДеревоМакета.СтруктураДокумента.МаксимальныйИдентификаторСвязи = ИдРесурса;
	УзелСвязейКартинки.Атрибуты.Вставить("Type", ТипКартинка);

	ИмяКартинки  = СтруктураКартинка.ИмяКартинки + Формат(ИдРесурса, "ЧГ=0");
	ИмяРесурса   = "media/" + ИмяКартинки + "." + РасширениеКартинки;
	УзелСвязейКартинки.Атрибуты.Вставить("Target", ИмяРесурса);
	
	СтруктураКартинка.Вставить("rId", "rId" + Формат(ИдРесурса, "ЧГ=0"));
	СтруктураКартинка.ИмяКартинки = ИмяКартинки;
	
	ТипыКонтента = ДеревоМакета.СтруктураДокумента.ТипыКонтента;
	УзлыРасширенийКартинки = Новый Массив;
	ПараметрыПоискаУзлов = ПараметрыПоискаУзлов();
	ПараметрыПоискаУзлов.ИмяАтрибута = "Extension";
	ПараметрыПоискаУзлов.ЗначенияАтрибута = РасширениеКартинки;
	НайтиУзлыПоСодержимому(ТипыКонтента, "Default", УзлыРасширенийКартинки, ПараметрыПоискаУзлов);
	Если УзлыРасширенийКартинки.Количество() = 0 Тогда
		УзелТипов = ТипыКонтента.Строки[0];
		УзелТипа = УзелТипов.Строки.Добавить();
		УзелТипа.ИмяТега = "Default";  
		УзелТипа.Атрибуты.Вставить("ContentType", "image/" + РасширениеКартинки);
		УзелТипа.Атрибуты.Вставить("Extension", РасширениеКартинки);
	КонецЕсли;
	
	ДвоичныеДанные = СтруктураКартинка.ДвоичныеДанные;
	ДвоичныеДанные.Записать(КаталогКартинок + СтруктураКартинка.ИмяКартинки + "." + СтруктураКартинка.РасширениеКартинки);
	
КонецПроцедуры

Процедура ДобавитьОбластиПереходныхУровней(Области, ДеревоДокумента)

	Области.Сортировать("Индекс");
	
	ДобавляемыеОбласти = Новый Массив;
	
	Для ИндексОбласти = 0 По Области.Количество()-1 Цикл
		Область = Области[ИндексОбласти];
		Если ИндексОбласти = Области.Количество()-1 Тогда
			ИндексНачалаСледующейОбласти = ИндексОкончанияОбласти(ДеревоДокумента);
		Иначе
			ИндексНачалаСледующейОбласти = Области[ИндексОбласти+1].Индекс;
		КонецЕсли;
		
		ДобавитьОбластиДоДостиженияИндекса(Область.УзелДереваДокумента, Область.Индекс, Область.УсловиеОбласти, ИндексНачалаСледующейОбласти, ДобавляемыеОбласти);					
		  
	КонецЦикла;
	
	Для Каждого СтруктураОбласти Из ДобавляемыеОбласти Цикл
		НоваяОбласть = Области.Добавить();
		ЗаполнитьЗначенияСвойств(НоваяОбласть, СтруктураОбласти);
		НоваяОбласть.Индекс = НоваяОбласть.УзелДереваДокумента.Индекс;
	КонецЦикла;
	
	Области.Сортировать("Индекс");
	
КонецПроцедуры

Процедура ДобавитьОбластиДоДостиженияИндекса(УзелДереваДокумента, ИндексНачалаТекущейОбласти, УсловиеОбласти, ИндексНачалаСледующейОбласти, ДобавляемыеОбласти)
	ИндексОкончанияТекущейОбласти = ИндексОкончанияОбласти(УзелДереваДокумента);					
	Если ИндексОкончанияТекущейОбласти + 1 < ИндексНачалаСледующейОбласти Тогда
		РодительОбласти = УзелДереваДокумента.Родитель;
		ИндексТекущейОбласти = РодительОбласти.Строки.Индекс(УзелДереваДокумента);
		Если ИндексТекущейОбласти = РодительОбласти.Строки.Количество() - 1 Тогда
			ДобавитьОбластиДоДостиженияИндекса(РодительОбласти, ИндексНачалаТекущейОбласти, УсловиеОбласти, ИндексНачалаСледующейОбласти, ДобавляемыеОбласти)
		Иначе
			ДобавляемыйУзел = РодительОбласти.Строки[ИндексТекущейОбласти+1];
			Если ДобавляемыйУзел.Индекс + 1 < ИндексНачалаСледующейОбласти И ДобавляемыйУзел.Индекс > ИндексНачалаТекущейОбласти Тогда
				СтруктураОбласти = Новый Структура("УзелДереваДокумента, УсловиеОбласти");
				СтруктураОбласти.УзелДереваДокумента = ДобавляемыйУзел;
				СтруктураОбласти.УсловиеОбласти = УсловиеОбласти;
				ДобавляемыеОбласти.Добавить(СтруктураОбласти);
				ДобавитьОбластиДоДостиженияИндекса(РодительОбласти, ИндексНачалаТекущейОбласти, УсловиеОбласти, ИндексНачалаСледующейОбласти, ДобавляемыеОбласти);
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
КонецПроцедуры

Функция ИндексОкончанияОбласти(УзелДереваДокумента)
	КоличествоСтрок = УзелДереваДокумента.Строки.Количество();
	Если КоличествоСтрок > 0 Тогда
		Возврат ИндексОкончанияОбласти(УзелДереваДокумента.Строки[КоличествоСтрок-1]);
	Иначе
		Возврат УзелДереваДокумента.Индекс;
	КонецЕсли;
КонецФункции

Процедура УдалитьТегиУсловныхОбластей(Индексы, ДеревоДокумента)
	Для Каждого Индекс Из Индексы Цикл
		Область = ДеревоДокумента.Строки.Найти(Индекс, "Индекс", Истина);
		Область.Родитель.Строки.Удалить(Область);
	КонецЦикла;
КонецПроцедуры

Процедура ДобавитьОбластьСУсловием(Области, Область)
	УзелСледующейОбласти = ГраницаСледующейОбласти(Область, Области);
	
	Если УзелСледующейОбласти = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	НайденнаяОбласть = Области.Найти(УзелСледующейОбласти, "УзелДереваДокумента");
	
	Если НайденнаяОбласть = Неопределено Тогда
		НайденнаяОбласть = Области.Добавить();
		НайденнаяОбласть.УзелДереваДокумента = УзелСледующейОбласти;
		НайденнаяОбласть.Индекс = НайденнаяОбласть.УзелДереваДокумента.Индекс;
	КонецЕсли;
	
	НайденнаяОбласть.УсловиеОбласти = УсловиеОбласти(Область);
КонецПроцедуры

#КонецОбласти

Процедура РазобратьКонтейнерДокументDOCX(Знач ПолноеИмяФайла, Знач ПутьКСтруктуреФайла)
	
	Попытка
		Архиватор = Новый ЧтениеZipФайла(ПолноеИмяФайла);
	Исключение
		УдалитьФайлы(ПолноеИмяФайла);
		ЗаписатьСобытияВЖурналРегистрации(СобытиеЖурналаРегистрации(), "Ошибка", ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		ВызватьИсключение(НСтр("ru = 'Не удалось открыть файл шаблона по причине:'") + Символы.ПС 
			+ ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
	КонецПопытки;
	
	Попытка
		Архиватор.ИзвлечьВсе(ПутьКСтруктуреФайла, РежимВосстановленияПутейФайловZIP.Восстанавливать);
	Исключение
		Архиватор.Закрыть();
		УдалитьФайлы(ПолноеИмяФайла);
		ЗаписатьСобытияВЖурналРегистрации(СобытиеЖурналаРегистрации(), "Ошибка", ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		ВызватьИсключение(НСтр("ru = 'Не удалось выполнить разбор файла шаблона по причине:'") + Символы.ПС 
			+ ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
	КонецПопытки;
	
	Архиватор.Закрыть();
	
КонецПроцедуры

Процедура СобратьКонтейнерДокументаDOCX(Знач ПолноеИмяФайла, Знач ПутьКСтруктуреФайла)
	
	Попытка
		Архиватор = Новый ЗаписьZipФайла(ПолноеИмяФайла);
	Исключение
		ЗаписатьСобытияВЖурналРегистрации(СобытиеЖурналаРегистрации(), "Ошибка", ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		ВызватьИсключение(НСтр("ru = 'Не удалось создать файл документа по причине:'") + Символы.ПС 
			+ ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
	КонецПопытки;
	
	МаскаУпаковкиФайлов = ОбщегоНазначенияКлиентСервер.ДобавитьКонечныйРазделительПути(ПутьКСтруктуреФайла) + "*";
	
	Попытка
		Архиватор.Добавить(МаскаУпаковкиФайлов, РежимСохраненияПутейZIP.СохранятьОтносительныеПути, РежимОбработкиПодкаталоговZIP.ОбрабатыватьРекурсивно);
		Архиватор.Записать();
	Исключение
		ЗаписатьСобытияВЖурналРегистрации(СобытиеЖурналаРегистрации(), "Ошибка", ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		ВызватьИсключение(НСтр("ru = 'Не удалось сформировать файл документа по причине:'") + Символы.ПС 
			+ ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
	КонецПопытки;
	
КонецПроцедуры

Функция СобратьФайлДокументаDOCX(ПечатнаяФорма)
	
	ИзменяемыеФайлы = Новый Соответствие;
	ИзменяемыеФайлы.Вставить("СвязиКонтента", ПечатнаяФорма.ИмяКаталога + УстановитьРазделительПути("\word\_rels\document.xml.rels"));
	ИзменяемыеФайлы.Вставить("ТипыКонтента",  ПечатнаяФорма.ИмяКаталога + УстановитьРазделительПути("\[Content_Types].xml"));
	ИзменяемыеФайлы.Вставить("Документ",      ПечатнаяФорма.ИмяКаталога + УстановитьРазделительПути("\word\document.xml"));
	
	// Удаляем файлы пустых колонтитулов
	КолонтитулВыведен = Новый Соответствие;
	
	Для Каждого Раздел Из ПечатнаяФорма.СтруктураДокумента.Разделы Цикл
		
		Для Каждого ЭлементКолонтитула Из Раздел.Значение.Колонтитулы Цикл
			
			Колонтитул = ЭлементКолонтитула.Значение;
			
			ИмяФайла = ПечатнаяФорма.ИмяКаталога + УстановитьРазделительПути("\word\") + Колонтитул.ИмяВнутр + ".xml";
			Если ПустаяСтрока(Колонтитул.Текст) Тогда
				Продолжить;
			КонецЕсли;
			
			ЗаписьXML = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8);
			ЗаписьXML.Записать(Колонтитул.Текст);
			ЗаписьXML.Закрыть();
			
			КолонтитулВыведен.Вставить(ЭлементКолонтитула.Ключ, ИСТИНА);
			
		КонецЦикла;
		
	КонецЦикла;
	
	МассивФайловКолонтитулов = Новый Массив;
	
	Для Каждого ЭлементКолонтитула Из ПечатнаяФорма.СтруктураДокумента.Колонтитулы Цикл
		
		Если КолонтитулВыведен.Получить(ЭлементКолонтитула.Ключ) = ИСТИНА Тогда
			Продолжить;
		КонецЕсли;
		
		Колонтитул = ЭлементКолонтитула.Значение;
		Колонтитул.Текст = "";
		
		ИмяФайла = ПечатнаяФорма.ИмяКаталога + УстановитьРазделительПути("\word\") + Колонтитул.ИмяВнутр + ".xml";
		УдалитьФайлы(ИмяФайла);
		МассивФайловКолонтитулов.Добавить(Колонтитул.ИмяВнутр);
		
	КонецЦикла;
	
	// Обрабатываем связи контента
	
	ЧтениеXML = ИнициализироватьЧтениеXML(ПечатнаяФорма.СтруктураДокумента.СвязиКонтента);
	ЗаписьXML = ИнициализироватьЗаписьXML("", ИзменяемыеФайлы.Получить("СвязиКонтента"));
	
	ПропуститьТэг    = Ложь;
	ПродолжитьЧтение = Истина;
	
	Пока Истина Цикл
		
		Если ПропуститьТэг Тогда
			ЧтениеXML.Пропустить();
			ПродолжитьЧтение = ЧтениеXML.Прочитать();
			ПропуститьТэг = Ложь;
		Иначе
			ПродолжитьЧтение = ЧтениеXML.Прочитать();
		КонецЕсли;
		
		Если НЕ ПродолжитьЧтение Тогда
			Прервать;
		КонецЕсли;
		
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "Relationship" Тогда
			
			ЗначениеАтрибута = ЧтениеXML.ПолучитьАтрибут("Target");
			
			Для Каждого ИмяФайлаКолонтитула Из МассивФайловКолонтитулов Цикл
				
				Если СтрНайти(ЗначениеАтрибута, ИмяФайлаКолонтитула) > 0 Тогда
					ПропуститьТэг = Истина;
					Прервать;
				КонецЕсли;
				
			КонецЦикла;
			
		КонецЕсли;
		
		Если НЕ ПропуститьТэг Тогда
			ЗаписатьЭлементXML(ЧтениеXML, ЗаписьXML);
		КонецЕсли;
		
	КонецЦикла;
	
	ПечатнаяФорма.СтруктураДокумента.СвязиКонтента = ЗаписьXML.Закрыть(); 
	
	// Обрабатываем типы контента
	
	ЧтениеXML = ИнициализироватьЧтениеXML(ПечатнаяФорма.СтруктураДокумента.ТипыКонтента);
	ЗаписьXML = ИнициализироватьЗаписьXML("", ИзменяемыеФайлы.Получить("ТипыКонтента"));
	
	ПропуститьТэг    = Ложь;
	ПродолжитьЧтение = Истина;
	
	Пока Истина Цикл
		
		Если ПропуститьТэг Тогда
			ЧтениеXML.Пропустить();
			ПродолжитьЧтение = ЧтениеXML.Прочитать();
			ПропуститьТэг = Ложь;
		Иначе
			ПродолжитьЧтение = ЧтениеXML.Прочитать();
		КонецЕсли;
		
		Если НЕ ПродолжитьЧтение Тогда
			Прервать;
		КонецЕсли;
		
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "Override" Тогда
			
			ЗначениеАтрибута = ЧтениеXML.ПолучитьАтрибут("PartName");
			
			Для Каждого ИмяФайлаКолонтитула Из МассивФайловКолонтитулов Цикл
				
				Если СтрНайти(ЗначениеАтрибута, ИмяФайлаКолонтитула) > 0 Тогда
					ПропуститьТэг = Истина;
					Прервать;
				КонецЕсли;
				
			КонецЦикла;
			
		КонецЕсли;
		
		Если НЕ ПропуститьТэг Тогда
			ЗаписатьЭлементXML(ЧтениеXML, ЗаписьXML);
		КонецЕсли;
		
	КонецЦикла;
	
	ПечатнаяФорма.СтруктураДокумента.ТипыКонтента = ЗаписьXML.Закрыть(); 
	
	// Формирование документа печатной формы
	
	ПорядковыйНомер = 1;
	
	ЗаписьXML = ИнициализироватьЗаписьXML("", ИзменяемыеФайлы.Получить("Документ"));
	
	НомерРаздела           = Неопределено;
	КоличествоОбластей     = ПечатнаяФорма.СтруктураДокумента.ПрисоединенныеОбласти.Количество();
	ИдентификаторДокумента = ПечатнаяФорма.СтруктураДокумента.ИдентификаторДокумента;
	
	Для Каждого Область Из ПечатнаяФорма.СтруктураДокумента.ПрисоединенныеОбласти Цикл
		
		Если Область.НомерРаздела = 0 Тогда
			Область.НомерРаздела = ?(НомерРаздела = Неопределено, 1, НомерРаздела);
		КонецЕсли;
		
		ВывестиПромежуточныйРаздел = ?(НомерРаздела <> Неопределено И НомерРаздела <> Область.НомерРаздела, Истина, Ложь);
		
		ЭтоПоследняяОбласть = ?(ПорядковыйНомер = КоличествоОбластей, Истина, Ложь);
		
		// Запись промежуточного раздела
		
		Если ВывестиПромежуточныйРаздел = Истина И ЭтоПоследняяОбласть = Ложь Тогда
			
			РазделКВыводу = ПечатнаяФорма.СтруктураДокумента.Разделы.Получить(НомерРаздела);
			
			Если РазделКВыводу <> Неопределено Тогда
				
				ТекстРаздела = ОбработатьРазделДокумента(ПечатнаяФорма.СтруктураДокумента, РазделКВыводу);
				
				ТэгОткрытияРаздела = "<w:p w:rsidR=""" + ИдентификаторДокумента + """ w:rsidRDefault=""" + ИдентификаторДокумента + """><w:pPr>";
				ТэгЗакрытияРаздела = "</w:pPr></w:p>";
				ТекстРаздела = ТэгОткрытияРаздела + ТекстРаздела + ТэгЗакрытияРаздела;
				ЗаписьXML.ЗаписатьБезОбработки(ТекстРаздела);
				
			КонецЕсли;
			
		КонецЕсли;
		
		// Запись тела
		
		ЧтениеXML = ИнициализироватьЧтениеXML(Область.Текст);
		
		Пока ЧтениеXML.Прочитать() Цикл
			
			Если ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ЧтениеXML.Имя = "w:body" Тогда
				Прервать;
			КонецЕсли;
			
			Если ПорядковыйНомер > 1 Тогда
				
				Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И (ЧтениеXML.Имя = "w:document" Или ЧтениеXML.Имя = "w:body") Тогда
					Продолжить;
				КонецЕсли;
				
			КонецЕсли;
			
			ЗаписатьЭлементXML(ЧтениеXML, ЗаписьXML);
			
		КонецЦикла;
		
		// Запись заключительного раздела
		
		Если ЭтоПоследняяОбласть Тогда
			
			РазделКВыводу = ПечатнаяФорма.СтруктураДокумента.Разделы.Получить(Область.НомерРаздела);
			Если РазделКВыводу <> Неопределено Тогда
				ТекстРаздела = ОбработатьРазделДокумента(ПечатнаяФорма.СтруктураДокумента, РазделКВыводу);
				ЗаписьXML.ЗаписатьБезОбработки(ТекстРаздела);
			КонецЕсли;
			
		КонецЕсли;
		
		ПорядковыйНомер = ПорядковыйНомер + 1;
		НомерРаздела = Область.НомерРаздела;
		
	КонецЦикла;
	
	ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрытие тэга </w:body>
	ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрытие тэга </w:document>
	
	ЗаписьXML.Закрыть();
	
	ПутьКДокументу = ПолучитьИмяВременногоФайла("DOCX");
	
	СобратьКонтейнерДокументаDOCX(ПутьКДокументу, ПечатнаяФорма.ИмяКаталога);
	
	Возврат ПутьКДокументу;
	
КонецФункции


// Параметры:
//  УзелПоиска - СтрокаДереваЗначений из см. ДеревоДокумента
//  ИндексРазмещения - Число
//
Процедура НайтиУзелРазмещенияШтампа(УзелПоиска, ИндексРазмещения) Экспорт
	Если УзелПоиска.Родитель.ИмяТега <> "w:body" И УзелПоиска.Родитель.ИмяТега <> "w:tc" Тогда
		УзелПоиска = УзелПоиска.Родитель;
		НайтиУзелРазмещенияШтампа(УзелПоиска, ИндексРазмещения);
	Иначе
		РодительУзлаПоиска = УзелПоиска.Родитель;
		ИндексРазмещения = РодительУзлаПоиска.Строки.Индекс(УзелПоиска);
		УзелПоиска = РодительУзлаПоиска;
	КонецЕсли;	
КонецПроцедуры

// Параметры:
//  УзелТаблицы - СтрокаДереваЗначений из см. ДеревоДокумента
//  УзелТекста - СтрокаДереваЗначений из см. ДеревоДокумента
//
Процедура ПеренестиПараметрыФорматирования(УзелТаблицы, УзелТекста) Экспорт
	
	Прогон = УзелТекста.Родитель;
	Абзац = Прогон.Родитель;
	
	ХарактеристикиТекста = НайтиУзел(Абзац, 1, "w:pPr");
	Если ХарактеристикиТекста = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ХарактеристикаПоложениеТекста = НайтиУзел(ХарактеристикиТекста, 1, "w:jc");
	Если ХарактеристикаПоложениеТекста = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ХарактеристикиТаблицы = НайтиУзел(УзелТаблицы, 1, "w:tblPr");
	
	ХарактеристикаПоложениеТаблицы = ХарактеристикиТаблицы.Строки.Добавить();
	ЗаполнитьЗначенияСвойств(ХарактеристикаПоложениеТаблицы, ХарактеристикаПоложениеТекста);
	ХарактеристикаПоложениеТаблицы.Атрибуты = ОбщегоНазначения.СкопироватьРекурсивно(ХарактеристикаПоложениеТекста.Атрибуты);
	
КонецПроцедуры

Процедура УдалитьНезначащиеАтрибуты(Дерево, НезначащиеАтрибуты) Экспорт
	Для Каждого Строка Из Дерево.Строки Цикл
		
		Для Каждого Атрибут Из НезначащиеАтрибуты Цикл
			Если Строка.Атрибуты.Получить(Атрибут) <> Неопределено Тогда
				Строка.Атрибуты.Удалить(Атрибут);
			КонецЕсли;
		КонецЦикла;
				
		УдалитьНезначащиеАтрибуты(Строка, НезначащиеАтрибуты);
	КонецЦикла;
КонецПроцедуры

Процедура ИнициализироватьСтруктуруМакета(Макет)
	
	ИмяКаталога            = Макет.ИмяКаталога;
	СтруктураДокумента     = Макет.СтруктураДокумента;
	ТаблицаСвязейКонтента  = СтруктураДокумента.ТаблицаСвязейКонтента;
	
	Файл = Новый Файл(ИмяКаталога + "[Content_Types].xml");
	Если Файл.Существует() Тогда
		Чтение = Новый ЧтениеТекста(Файл.ПолноеИмя, КодировкаТекста.UTF8);
		ТекстФайла = Чтение.Прочитать();
		СтруктураДокумента.ТипыКонтента = ТекстФайла;
	КонецЕсли;
	
	КаталогФайлаСвязей = ИмяКаталога + УстановитьРазделительПути("\word\_rels\");
	
	Файл = Новый Файл(КаталогФайлаСвязей + "document.xml.rels");
	Если Файл.Существует() Тогда
		ЧтениеXML = Новый ЧтениеТекста(Файл.ПолноеИмя, КодировкаТекста.UTF8);
		ТекстФайла = ЧтениеXML.Прочитать();
		СтруктураДокумента.СвязиКонтента = ТекстФайла;
	
		ЧтениеXML = ИнициализироватьЧтениеXML(ТекстФайла);
		Пока ЧтениеXML.Прочитать() Цикл
			Если НЕ (ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "Relationship") Тогда
				Продолжить;
			КонецЕсли;
			
			ИдРесурса    = ЧтениеXML.ПолучитьАтрибут("Id");
			
			СтрокаЛишнихСимволов = СтрСоединить(СтрРазделить(ИдРесурса, "0123456789"));
			НомерРесурсаСтрокой = СтрСоединить(СтрРазделить(ИдРесурса, СтрокаЛишнихСимволов));
			
			НомерРесурса = Число(НомерРесурсаСтрокой);
			
			НоваяСтрока = ТаблицаСвязейКонтента.Добавить();
			НоваяСтрока.ИмяРесурса   = ЧтениеXML.ПолучитьАтрибут("Target");
			НоваяСтрока.ИдРесурса    = ИдРесурса;
			НоваяСтрока.НомерРесурса = НомерРесурса;
		КонецЦикла;
	КонецЕсли;
	
	// Получить таблицу номеров ресурсов
	
	КаталогСоСтруктуройФайла = ИмяКаталога + "word" + ПолучитьРазделительПути();
	
	Файл = Новый Файл(КаталогСоСтруктуройФайла + "document.xml"); //@Non-NLS
	Если Файл.Существует() Тогда
		ЧтениеXML = ИнициализироватьЧтениеXML(Файл.ПолноеИмя, 1);
		ПараметрыАнализа = Новый Структура("ТипАнализа", 1);
		РазбитьТекстШаблонаНаОбласти(ЧтениеXML, СтруктураДокумента, ПараметрыАнализа);
	КонецЕсли;
	
	Для Каждого Раздел Из СтруктураДокумента.Разделы Цикл
		ЧтениеXML = ИнициализироватьЧтениеXML(Раздел.Значение.Текст);
		ВыделитьИзРазделаКолонтитулы(ЧтениеXML, СтруктураДокумента, Раздел.Значение);
	КонецЦикла;
	
	СтруктурныеФайлы = НайтиФайлы(КаталогСоСтруктуройФайла, "*.xml");
	Для Каждого Файл Из СтруктурныеФайлы Цикл
		Если НЕ (Лев(Файл.ИмяБезРасширения, 6) = "header") И НЕ (Лев(Файл.ИмяБезРасширения, 6) = "footer") Тогда
			Продолжить;
		КонецЕсли;
		
		Колонтитул = СтруктураДокумента.Колонтитулы.Получить(Файл.Имя); // см. ОбластьКолонтитула
		Если Колонтитул = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		СтруктураДокумента.Колонтитулы.Удалить(Файл.Имя);
		СтруктураДокумента.Колонтитулы.Вставить(Колонтитул.Имя + "_" + Формат(Колонтитул.НомерРаздела, "ЧГ=0"), Колонтитул);
		
		ЧтениеXML = ИнициализироватьЧтениеXML(Файл.ПолноеИмя, 1);
		ПараметрыАнализа = Новый Структура("ТипАнализа, СтруктураАнализа", 2, Колонтитул);
		РазбитьТекстШаблонаНаОбласти(ЧтениеXML, СтруктураДокумента, ПараметрыАнализа);
	КонецЦикла;
	
КонецПроцедуры

Процедура ИнициализироватьСтруктуруПечатнойФормы(ПечатнаяФорма, Макет)
	
	ИмяКаталога        = ПечатнаяФорма.ИмяКаталога;
	СтруктураДокумента = ПечатнаяФорма.СтруктураДокумента;
	
	СтруктураДокумента.ИдентификаторДокумента = Макет.СтруктураДокумента.ИдентификаторДокумента;
	СтруктураДокумента.КаталогКартинок        = ИмяКаталога + УстановитьРазделительПути("\word\media\");
	СтруктураДокумента.ТаблицаСвязейКонтента = Макет.СтруктураДокумента.ТаблицаСвязейКонтента.Скопировать();
	
	Файл = Новый Файл(ИмяКаталога + "[Content_Types].xml");
	Если Файл.Существует() Тогда
		ЧтениеXML = Новый ЧтениеТекста(Файл.ПолноеИмя,КодировкаТекста.UTF8);
		ТекстФайла = ЧтениеXML.Прочитать();
		СтруктураДокумента.ТипыКонтента = ТекстФайла;
	КонецЕсли;
	
	КаталогФайлаСвязей = ИмяКаталога + УстановитьРазделительПути("\word\_rels\");
	
	Файл = Новый Файл(КаталогФайлаСвязей + "document.xml.rels");
	Если Файл.Существует() Тогда
		ЧтениеXML = Новый ЧтениеТекста(Файл.ПолноеИмя, КодировкаТекста.UTF8);
		ТекстФайла = ЧтениеXML.Прочитать();
		СтруктураДокумента.СвязиКонтента = ТекстФайла;
	КонецЕсли;
	
	КаталогСоСтруктуройФайла = ИмяКаталога + "word" + ПолучитьРазделительПути();
	МаскаФайлов ="*.xml";
	СтруктурныеФайлы = НайтиФайлы(КаталогСоСтруктуройФайла, МаскаФайлов);
	
	Для Каждого Файл Из СтруктурныеФайлы Цикл
		Если Файл.ИмяБезРасширения = "document" Тогда
			ЗаписьXML = Новый ЗаписьТекста(Файл.ПолноеИмя, КодировкаТекста.UTF8);
			ЗаписьXML.Записать("");
		КонецЕсли;
		
		Если Лев(Файл.ИмяБезРасширения, 6) = "header" Тогда
			ЗаписьXML = Новый ЗаписьТекста(Файл.ПолноеИмя,КодировкаТекста.UTF8);
			ЗаписьXML.Записать("");
		КонецЕсли;
		
		Если Лев(Файл.ИмяБезРасширения, 6) = "footer" Тогда
			ЗаписьXML = Новый ЗаписьТекста(Файл.ПолноеИмя, КодировкаТекста.UTF8);
			ЗаписьXML.Записать("");
		КонецЕсли;
	КонецЦикла;
	
	// Текст копирования колонтитулов и разделов из макета
	Для Каждого Раздел Из Макет.СтруктураДокумента.Разделы Цикл
		ДобавитьВСтруктуруДокументаРаздел(СтруктураДокумента, Раздел.Значение);
	КонецЦикла;
	
	Для Каждого Колонтитул Из Макет.СтруктураДокумента.Колонтитулы Цикл
		
		ДобавитьВСтруктуруДокументаКолонтитул(СтруктураДокумента, Колонтитул.Значение);
		СтруктураКолонтитула = СтруктураДокумента.Колонтитулы.Получить(Колонтитул.Ключ);
		Если СтруктураКолонтитула <> Неопределено Тогда
			СтруктураКолонтитула.Текст = "";
		КонецЕсли;
		
	КонецЦикла;
	
	Абзац = Макет.СтруктураДокумента.ОбластиДокумента.Получить("Абзац");
	
	Если Абзац <> Неопределено Тогда
		ДобавитьВСтруктуруДокументаОбластьДокумента(СтруктураДокумента, Абзац);
	КонецЕсли;
	
КонецПроцедуры

Процедура ЗаполнитьПараметрыОбласти(ПечатнаяФорма, Область, ДанныеОбъекта)
	
	ОбработатьТекст = ЛОЖЬ;
	СтруктураРазбораXML = ИнициализироватьРазборXML();
	
	ОткрытаТаблица       = Ложь; 
	ОткрытаКлеткаТаблицы = Ложь;
	УстановленАтрибутСохраненияПробелов = Ложь;
	
	ШиринаТаблицы         = 0;
	ШиринаКлеткиТаблицы   = 0;
	
	РазрешениеОсновногоЭкрана = СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере().Получить("РазрешениеОсновногоЭкрана");
	РазрешениеОсновногоЭкрана = ?(РазрешениеОсновногоЭкрана = Неопределено, 72, РазрешениеОсновногоЭкрана);
	
	ЧтениеXML = ИнициализироватьЧтениеXML(Область.Текст);
	ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "Область", "");
	
	Пока ЧтениеXML.Прочитать() Цикл
		
		Если ЧтениеНачалаТекстаСтроки(СтруктураРазбораXML, ЧтениеXML) Тогда
			ОбработатьТекст = ИСТИНА;
			УстановленАтрибутСохраненияПробелов = Ложь;
		КонецЕсли;
		
		Если ЧтениеКонцаТекстаСтроки(СтруктураРазбораXML, ЧтениеXML) Тогда
			ОбработатьТекст = ЛОЖЬ;
		КонецЕсли;
		
		Если ЧтениеНачалаТаблицы(СтруктураРазбораXML, ЧтениеXML) Тогда
			ОткрытаТаблица = Истина;
		КонецЕсли;
		
		Если ОткрытаТаблица И ЧтениеНачалаШириныТаблицы(СтруктураРазбораXML, ЧтениеXML) Тогда
			УстановитьШиринуПоля(ЧтениеXML, ШиринаТаблицы);
		КонецЕсли;
		
		Если ОткрытаТаблица И ЧтениеНачалаКлеткиТаблицы(СтруктураРазбораXML, ЧтениеXML) Тогда
			ОткрытаКлеткаТаблицы = Истина;
		КонецЕсли;
		
		Если ОткрытаКлеткаТаблицы И ЧтениеНачалаШириныКлеткиТаблицы(СтруктураРазбораXML, ЧтениеXML) Тогда
			УстановитьШиринуПоля(ЧтениеXML, ШиринаКлеткиТаблицы, ШиринаТаблицы);
		КонецЕсли;
		
		Если ЧтениеКонцаКлеткиТаблицы(СтруктураРазбораXML, ЧтениеXML) Тогда
			ОткрытаКлеткаТаблицы = Ложь;
			ШиринаКлеткиТаблицы  = 0;
		КонецЕсли;
		
		Если ЧтениеКонцаТаблицы(СтруктураРазбораXML, ЧтениеXML) Тогда
			ОткрытаТаблица = Ложь;
			ШиринаТаблицы  = 0;
		КонецЕсли;
			
		Если ОбработатьТекст И ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
			
			ТекстУзла = ЧтениеXML.Значение;
			
			ПараметрыИзТекста = Новый Массив;
			
			ВыделитьПараметры(ПараметрыИзТекста, ТекстУзла);
			
			ВыводТекста = Истина;
			ВыводКартинки = Ложь;
			ЗначениеПараметра = Неопределено;
			
			Для Каждого ПараметрТекст Из ПараметрыИзТекста Цикл
				
				Если ДанныеОбъекта.Свойство(ПараметрТекст, ЗначениеПараметра) Тогда
					Если ТипЗнч(ЗначениеПараметра) = Тип("Структура") Тогда
						РазмерыКартинки = Новый Структура("Ширина,Высота",0,0);
						ЗаполнитьЗначенияСвойств(РазмерыКартинки, ЗначениеПараметра);
						ЗначениеПараметра = СокрЛП(ЗначениеПараметра.АдресКартинки);
					Иначе
						ЗначениеПараметра = Строка(ЗначениеПараметра);
					КонецЕсли;
				КонецЕсли;
				
				Если ТипЗнч(ЗначениеПараметра) = Тип("Строка") И НЕ СтрНачинаетсяС(ЗначениеПараметра, "e1cib/tempstorage") Тогда
					ТекстУзла = СтрЗаменить(ТекстУзла, "{v8 " + ПараметрТекст + "}", ЗначениеПараметра);
				ИначеЕсли ТипЗнч(ЗначениеПараметра) = Тип("Строка") И СтрНачинаетсяС(ЗначениеПараметра, "e1cib/tempstorage") Тогда
					ТекстУзла = ЗначениеПараметра;
					ВыводТекста = Ложь;
					ВыводКартинки = Истина;
					Прервать;
				КонецЕсли;
				
			КонецЦикла;
			
			Если ВыводТекста Тогда
				
				ЗаписатьТекстВПотоки(СтруктураРазбораXML, ЧтениеXML, "Область", ТекстУзла, УстановленАтрибутСохраненияПробелов);
				
			ИначеЕсли ВыводКартинки Тогда
				
				ДвоичныеДанные = ПолучитьИзВременногоХранилища(ТекстУзла); // ДвоичныеДанные - 
				
				СтруктураКартинка = Новый Структура;
				СтруктураКартинка.Вставить("ДвоичныеДанные",     ДвоичныеДанные);
				СтруктураКартинка.Вставить("ИмяКартинки",        "image");
				СтруктураКартинка.Вставить("КаталогКартинок",    ПечатнаяФорма.СтруктураДокумента.КаталогКартинок);
				
				ПараметрыКартинки = ПолучитьАтрибутыИзображения(ДвоичныеДанные);
				
				Если ПараметрыКартинки.Количество() = 0 ИЛИ ПараметрыКартинки.ТипИзображения = Null Тогда
					ЗаписатьТекстВПотоки(СтруктураРазбораXML, ЧтениеXML, "Область", ТекстУзла);
					Продолжить;
				КонецЕсли;
				
				Если НЕ ШиринаКлеткиТаблицы = 0 Тогда
					
					ОтношениеВысотыКШирине = ПараметрыКартинки.Высота / ПараметрыКартинки.Ширина;
					
					ШиринаКартинки = ШиринаКлеткиТаблицы * 914400 / РазрешениеОсновногоЭкрана / 20;
					ВысотаКартинки = ОтношениеВысотыКШирине * ШиринаКлеткиТаблицы * 914400 / РазрешениеОсновногоЭкрана / 20;
					
				Иначе
					
					Если РазмерыКартинки.Высота <> 0 ИЛИ РазмерыКартинки.Ширина <> 0 Тогда
						
						КоэффициентПересчета = 914400/2.54/10;
						Если РазмерыКартинки.Ширина <> 0 Тогда 
							ШиринаКартинки = КоэффициентПересчета * РазмерыКартинки.Ширина;
							КоэффициентМасштабирования = ШиринаКартинки/ПараметрыКартинки.Ширина;
						КонецЕсли;
						
						Если РазмерыКартинки.Высота <> 0 Тогда 
							ВысотаКартинки = КоэффициентПересчета * РазмерыКартинки.Высота;
							КоэффициентМасштабирования = ВысотаКартинки/ПараметрыКартинки.Высота;
						КонецЕсли;
						
						Если РазмерыКартинки.Ширина = 0 Тогда
							ШиринаКартинки = КоэффициентМасштабирования*ПараметрыКартинки.Ширина;
						КонецЕсли;
						
						Если РазмерыКартинки.Высота = 0 Тогда
							ВысотаКартинки = КоэффициентМасштабирования*ПараметрыКартинки.Высота;
						КонецЕсли;
						
					Иначе
						КоэффициентМасштаба = 2;
						КоэффициентПропорций = 914400 / (РазрешениеОсновногоЭкрана * КоэффициентМасштаба);
						
						ШиринаКартинки = КоэффициентПропорций * ПараметрыКартинки.Ширина;
						ВысотаКартинки = КоэффициентПропорций * ПараметрыКартинки.Высота;
					КонецЕсли;
				КонецЕсли;
				
				ШиринаКартинки = Окр(ШиринаКартинки, 0);
				ВысотаКартинки = Окр(ВысотаКартинки, 0);
				
				СтруктураКартинка.Вставить("РасширениеКартинки", СтрЗаменить(ПараметрыКартинки.ТипИзображения, "image/", ""));
				СтруктураКартинка.Вставить("ШиринаКартинки",     ШиринаКартинки);
				СтруктураКартинка.Вставить("ВысотаКартинки",     ВысотаКартинки);
				
				
				ВнестиКартинкуВБиблиотекуДокумента(ПечатнаяФорма.СтруктураДокумента, СтруктураКартинка);
				ШаблонКартинкиXML = ПолучитьШаблонКартинки();
				ПодготовитьШаблонКартинки(ШаблонКартинкиXML, СтруктураКартинка);
				ВнестиТекстКартинкиВДокумент(СтруктураРазбораXML.ПотокиЗаписи.Область.Поток, СтруктураКартинка);
				
			КонецЕсли
			
		Иначе
			ЗаписатьЭлементXMLВПоток(СтруктураРазбораXML, ЧтениеXML, ПечатнаяФорма.СтруктураДокумента, УстановленАтрибутСохраненияПробелов);
		КонецЕсли;
		
	КонецЦикла;
	
	Область.Текст = ЗавершитьЗаписьВПоток(СтруктураРазбораXML, "Область");
	
КонецПроцедуры

// Параметры:
//  ПечатнаяФорма - см. ИнициализироватьПечатнуюФорму
//  Область - Структура:
//   * Имя - Строка
//   * Текст - Строка
//   * НомерРаздела - Число
//   * Гиперссылки - Массив из см. СтруктураГиперссылки
//  ДанныеОбъекта - Структура, Неопределено, КлючИЗначение
//
Процедура ЗаполнитьПараметрыГиперссылок(ПечатнаяФорма, Область, ДанныеОбъекта)
	
	Если Область.Гиперссылки.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	СтруктураДокумента = ПечатнаяФорма.СтруктураДокумента;
	ТаблицаСвязейКонтента = СтруктураДокумента.ТаблицаСвязейКонтента;
	
	ДеревоСвязей = ПрочитатьСтрокуXMLВДерево(СтруктураДокумента.СвязиКонтента);
	УзелВзаимосвязей = ДеревоСвязей.Строки[0];
	МассивНайденныхУзлов = Новый Массив;
	ПараметрыПоискаУзлов = ПараметрыПоискаУзлов();
	ПараметрыПоискаУзлов.ИмяАтрибута = "Type";
	ПараметрыПоискаУзлов.ЗначенияАтрибута = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
	НайтиУзлыПоСодержимому(ДеревоСвязей, "Relationship", МассивНайденныхУзлов, ПараметрыПоискаУзлов);
	
	Для ИндексМассива = 0 По Область.Гиперссылки.ВГраница() Цикл
		
		ГиперСсылка 	= Область.Гиперссылки[ИндексМассива];
		ИДРесурса		= ГиперСсылка.ИДРесурса;
		ИмяПараметра	= ГиперСсылка.ИмяПараметра;
		
		Если Не ПустаяСтрока(ИмяПараметра) Тогда
			СтрокаСсылка      = ГиперСсылка.Ссылка;
			ЗначениеПараметра = "";
			
			Если ДанныеОбъекта.Свойство(ИмяПараметра, ЗначениеПараметра) Тогда
				ЗначениеПараметра = КодироватьСтроку(СокрЛП(ЗначениеПараметра), СпособКодированияСтроки.КодировкаURL);
			КонецЕсли;
			УстанавливаемоеЗначение = СтрЗаменить(СтрокаСсылка, "{v8 " + ИмяПараметра +"}" , ЗначениеПараметра);
			
			СтрокаСвязейКонтента = ТаблицаСвязейКонтента.Найти(ИДРесурса, "ИДРесурса");
			
			Если РаскодироватьСтроку(СтрокаСвязейКонтента.ИмяРесурса, СпособКодированияСтроки.КодировкаURL) = СтрокаСсылка Тогда
				СтрокаСвязейКонтента.ИмяРесурса 	= УстанавливаемоеЗначение;
				
				Для Каждого УзелГиперссылки Из МассивНайденныхУзлов Цикл
					Если УзелГиперссылки.Атрибуты["Id"] = ИДРесурса Тогда
						УзелГиперссылки.Атрибуты.Вставить("Target", УстанавливаемоеЗначение);
						Прервать;
					КонецЕсли;
				КонецЦикла;
				
			Иначе
				ТаблицаСвязейКонтента.Сортировать("НомерРесурса Возр");
				НовыйНомерРесурса = ТаблицаСвязейКонтента[ТаблицаСвязейКонтента.Количество() - 1].НомерРесурса + 1;
				
				НовыйИДРесурса = "rId" + Формат(НовыйНомерРесурса, "ЧГ=0");
				
				НоваяСтрокаСсылки 				= ТаблицаСвязейКонтента.Добавить();
				НоваяСтрокаСсылки.НомерРесурса	= НовыйНомерРесурса;
				НоваяСтрокаСсылки.ИДРесурса		= НовыйИДРесурса;
				НоваяСтрокаСсылки.ИмяРесурса 	= УстанавливаемоеЗначение;
				
				НоваяСвязь = УзелВзаимосвязей.Строки.Добавить();
				НоваяСвязь.ИмяТега = "Relationship";
				НоваяСвязь.Атрибуты = Новый Соответствие;
				НоваяСвязь.Атрибуты.Вставить("Target", УстанавливаемоеЗначение);
				НоваяСвязь.Атрибуты.Вставить("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink");
				НоваяСвязь.Атрибуты.Вставить("Id", НовыйИДРесурса);
				НоваяСвязь.Атрибуты.Вставить("TargetMode", "External");
				
				Область.Текст = СтрЗаменить(Область.Текст, "r:id="""+ИДРесурса+"""", "r:id="""+НовыйИДРесурса+"""");
				
			КонецЕсли;
			
		КонецЕсли;
		
	КонецЦикла;
	
	СтруктураДокумента.СвязиКонтента = ПоместитьДеревоВСтрокуXML(ДеревоСвязей);
	
	
КонецПроцедуры

Процедура ВыделитьПараметры(МассивПараметров, Знач Текст)

	НачалоПараметра = СтрНайти(Текст, "{v8 ");
	
	Если НачалоПараметра > 0 Тогда
		
		Текст = Прав(Текст, СтрДлина(Текст) - (НачалоПараметра+3));
		КонецПараметра = СтрНайти(Текст, "}");
		Если КонецПараметра > 0 Тогда
			ТекстПараметра = СокрЛП(Лев(Текст, КонецПараметра-1));
			МассивПараметров.Добавить(ТекстПараметра);
			Текст = Прав(Текст, СтрДлина(Текст) - (СтрДлина(ТекстПараметра) + 1));
		КонецЕсли;
		
		НачалоПараметра = СтрНайти(Текст, "{v8 ");
		Если НачалоПараметра > 0 Тогда
			ВыделитьПараметры(МассивПараметров, Текст);
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

Процедура УстановитьШиринуПоля(ЧтениеXML, Ширина, Знач ШиринаТаблицы = 0)
	
	ТипDXA = Ложь;
	ТипPCT = Ложь;
	
	Ширина    = ЧтениеXML.ПолучитьАтрибут("w:w");
	ТипШирины = ЧтениеXML.ПолучитьАтрибут("w:type");
	
	Если ТипШирины = "auto" Тогда
		ТипDXA = Ложь;
	ИначеЕсли ТипШирины = "dxa" Тогда
		ТипDXA = Истина;
	ИначеЕсли ТипШирины = "pct" Тогда
		ТипPCT = Истина;
	КонецЕсли;
	
	Если НЕ ТипDXA ИЛИ (ТипPCT И ШиринаТаблицы = 0) Тогда
		Ширина = 0;
	ИначеЕсли ТипPCT И НЕ ШиринаТаблицы = 0 Тогда
		
		// 5000 - значение равное 100% для типа "pct".
		// ПолеРодитель - в значениях dxa.
		
		Ширина = ШиринаТаблицы * Ширина / 50 / 100;
		
	КонецЕсли;
	
КонецПроцедуры

Функция ПолучитьШаблонКартинки()
	
	ШаблонКартинкиXML =
	"<w:drawing>
	|	<wp:inline distT=""0"" distB=""0"" distL=""0"" distR=""0"">
	|		<wp:extent cx=""%6"" cy=""%7""/>
	|		<wp:effectExtent l=""0"" t=""0"" r=""0"" b=""0""/>
	|		<wp:docPr id=""%1"" name=""%2""/>
	|		<wp:cNvGraphicFramePr>
	|			<a:graphicFrameLocks xmlns:a=""http://schemas.openxmlformats.org/drawingml/2006/main"" noChangeAspect=""1""/>
	|		</wp:cNvGraphicFramePr>
	|		<a:graphic xmlns:a=""http://schemas.openxmlformats.org/drawingml/2006/main"">
	|			<a:graphicData uri=""http://schemas.openxmlformats.org/drawingml/2006/picture"">
	|				<pic:pic xmlns:pic=""http://schemas.openxmlformats.org/drawingml/2006/picture"">
	|					<pic:nvPicPr>
	|						<pic:cNvPr id=""%1"" name=""%2"" descr=""%3""/>
	|						<pic:cNvPicPr>
	|							<a:picLocks noChangeAspect=""1"" noChangeArrowheads=""1""/>
	|						</pic:cNvPicPr>
	|					</pic:nvPicPr>
	|					<pic:blipFill>
	|						<a:blip r:embed=""%4"">
	|							<a:extLst>
	|								<a:ext uri=""%5"">
	|									<a14:useLocalDpi xmlns:a14=""http://schemas.microsoft.com/office/drawing/2010/main"" val=""0""/>
	|								</a:ext>
	|							</a:extLst>
	|						</a:blip>
	|						<a:srcRect/>
	|						<a:stretch>
	|							<a:fillRect/>
	|						</a:stretch>
	|					</pic:blipFill>
	|					<pic:spPr bwMode=""auto"">
	|						<a:xfrm>
	|							<a:off x=""0"" y=""0""/>
	|							<a:ext cx=""%6"" cy=""%7""/>
	|						</a:xfrm>
	|						<a:prstGeom prst=""rect"">
	|							<a:avLst/>
	|						</a:prstGeom>
	|						<a:noFill/>
	|						<a:ln>
	|							<a:noFill/>
	|						</a:ln>
	|					</pic:spPr>
	|				</pic:pic>
	|			</a:graphicData>
	|		</a:graphic>
	|	</wp:inline>
	|</w:drawing>";
	
	Возврат ШаблонКартинкиXML;
	
КонецФункции

Процедура ПодготовитьШаблонКартинки(ШаблонКартинки, СтруктураКартинка)
	
	// Параметры подстановки
	// 1 - id
	// 2 - name
	// 3 - descr
	// 4 - rId
	// 5 - uri
	// 6 - cx
	// 7 - cy
	ОбработанныйШаблонКартинки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонКартинки, 
		"0",
		СтруктураКартинка.ИмяКартинки,
		СтруктураКартинка.ИмяКартинки,
		СтруктураКартинка.rId,
		"{28A0092B-C50C-407E-A947-70E740481C1C}", 
		Формат(СтруктураКартинка.ШиринаКартинки, "ЧГ=0"),
		Формат(СтруктураКартинка.ВысотаКартинки, "ЧГ=0"));
										   
	СтруктураКартинка.Вставить("ТекстКартинки", ОбработанныйШаблонКартинки);
	
КонецПроцедуры

Процедура ВнестиКартинкуВБиблиотекуДокумента(СтруктураДокумента, СтруктураКартинка)
	
	КаталогMedia = Новый Файл(СтруктураКартинка.КаталогКартинок);
	ТипКартинка = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
	
	Если НЕ КаталогMedia.Существует() Тогда
		СоздатьКаталог(СтруктураКартинка.КаталогКартинок);
	КонецЕсли;
	
	// Добавить строку в rels файл
	ЧтениеXML = ИнициализироватьЧтениеXML(СтруктураДокумента.СвязиКонтента);
	ЗаписьXML = ИнициализироватьЗаписьXML("");
	
	СтруктураДокумента.ТаблицаСвязейКонтента.Сортировать("НомерРесурса Возр");
	МаксНомерРесурса = СтруктураДокумента.ТаблицаСвязейКонтента[СтруктураДокумента.ТаблицаСвязейКонтента.Количество() - 1].НомерРесурса;
	
	Пока ЧтениеXML.Прочитать() Цикл
		
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ЧтениеXML.Имя = "Relationships" Тогда
			
			НомерРесурса = МаксНомерРесурса + 1;
			ИдРесурса    = "rId" + Формат(МаксНомерРесурса + 1, "ЧГ=0");
			ИмяКартинки  = СтруктураКартинка.ИмяКартинки + ИдРесурса;
			ИмяРесурса   = "media/" + ИмяКартинки + "." + СтруктураКартинка.РасширениеКартинки;
			
			ДобавитьСтрокуВТаблицуСвязейКонтента(СтруктураДокумента, ИмяРесурса, ИдРесурса, НомерРесурса);
			
			СтруктураКартинка.Вставить("rId", ИдРесурса);
			СтруктураКартинка.ИмяКартинки = ИмяКартинки;
			
			ЗаписьXML.ЗаписатьНачалоЭлемента("Relationship");
			ЗаписьXML.ЗаписатьАтрибут("Target", ИмяРесурса);
			ЗаписьXML.ЗаписатьАтрибут("Type",   ТипКартинка);
			ЗаписьXML.ЗаписатьАтрибут("Id",     ИдРесурса);
			ЗаписьXML.ЗаписатьКонецЭлемента();
			
			ЗаписатьЭлементXML(ЧтениеXML, ЗаписьXML);
			
			ДобавитьРасширениеКартинкиВТипыКонтента(СтруктураДокумента, СтруктураКартинка);
			
		Иначе
			ЗаписатьЭлементXML(ЧтениеXML, ЗаписьXML);
		КонецЕсли;
		
	КонецЦикла;
	
	ЧтениеXML.Закрыть();
	СтруктураДокумента.СвязиКонтента = ЗаписьXML.Закрыть();
	
	// Записать картинку в каталог media
	ДвоичныеДанные = СтруктураКартинка.ДвоичныеДанные;
	ДвоичныеДанные.Записать(СтруктураКартинка.КаталогКартинок + СтруктураКартинка.ИмяКартинки + "." + СтруктураКартинка.РасширениеКартинки);
	
КонецПроцедуры

Процедура ВнестиТекстКартинкиВДокумент(ЗаписьXML, СтруктураКартинка)
	
	ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрывается текстовый тэг параметра w:t.
	ЗаписьXML.ЗаписатьБезОбработки(СтруктураКартинка.ТекстКартинки);
	ЗаписьXML.ЗаписатьНачалоЭлемента("w:t");
	
КонецПроцедуры

Процедура ДобавитьРасширениеКартинкиВТипыКонтента(СтруктураДокумента, СтруктураКартинка)
	
	ДобавленныеРасширения = СтруктураДокумента.РасширенияКартинок;
	РасширениеКартинки    = СтруктураКартинка.РасширениеКартинки; 
	
	Если НЕ ДобавленныеРасширения.Найти(РасширениеКартинки) = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ЧтениеXML = ИнициализироватьЧтениеXML(СтруктураДокумента.ТипыКонтента);
	
	ЗаписьXML = ИнициализироватьЗаписьXML("");
	
	РасширениеИмеется = Ложь;
	
	Пока ЧтениеXML.Прочитать() Цикл
		
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "Default" Тогда
			
			ЗначениеExtension = ЧтениеXML.ЗначениеАтрибута("Extension");
			
			Если ЗначениеExtension = РасширениеКартинки Тогда
				РасширениеИмеется = Истина;
			КонецЕсли;
			
			ЗаписатьЭлементXML(ЧтениеXML, ЗаписьXML);
			
		ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ЧтениеXML.Имя = "Types" Тогда
			
			Если НЕ РасширениеИмеется Тогда
			
				ЗаписьXML.ЗаписатьНачалоЭлемента("Default");
				ЗаписьXML.ЗаписатьАтрибут("ContentType", "image/" + РасширениеКартинки);
				ЗаписьXML.ЗаписатьАтрибут("Extension", РасширениеКартинки);
				ЗаписьXML.ЗаписатьКонецЭлемента();
				
				ДобавленныеРасширения.Добавить(РасширениеКартинки);
			
			КонецЕсли;
			
			ЗаписатьЭлементXML(ЧтениеXML, ЗаписьXML);
			
		Иначе
			
			ЗаписатьЭлементXML(ЧтениеXML, ЗаписьXML);
			
		КонецЕсли;
		
	КонецЦикла;
	
	ЧтениеXML.Закрыть();
	СтруктураДокумента.ТипыКонтента = ЗаписьXML.Закрыть();
	
КонецПроцедуры

#Область ПростыеОперацииСДаннымиXML

Функция ИнициализироватьЗаписьXML(КорневойТэг, ПутьКФайлу = "", Кодировка = "UTF-8", ЗаписатьОбъявление = Истина)
	
	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.Отступ = Ложь;
	Если ПустаяСтрока(ПутьКФайлу) Тогда
		ЗаписьXML.УстановитьСтроку();
	Иначе
		ЗаписьXML.ОткрытьФайл(ПутьКФайлу)
	КонецЕсли;
	
	Если ЗаписатьОбъявление Тогда
		ЗаписьXML.ЗаписатьБезОбработки("<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>");
	КонецЕсли;
	
	Если Не ПустаяСтрока(КорневойТэг) Тогда
		ЗаписьXML.ЗаписатьНачалоЭлемента(КорневойТэг);
	КонецЕсли;
	
	Возврат ЗаписьXML;
	
КонецФункции

Функция ИнициализироватьЧтениеXML(ДанныеЧтения, ТипДанных = 0)
	
	ЧтениеXML = Новый ЧтениеXML;
	Если ТипДанных = 0 Тогда
		ЧтениеXML.УстановитьСтроку(ДанныеЧтения);
	Иначе
		ЧтениеXML.ОткрытьФайл(ДанныеЧтения);
	КонецЕсли;
	
	ЧтениеXML.ИгнорироватьПробелы = ЛОЖЬ;
	
	Возврат ЧтениеXML;
	
КонецФункции

Процедура ЗаписатьЭлементXML(ЧтениеXML, ЗаписьXML, Текст = Неопределено)
	
	Если ЧтениеXML.ТипУзла = ТипУзлаXML.ИнструкцияОбработки Тогда
		
		ЗаписьXML.ЗаписатьИнструкциюОбработки(ЧтениеXML.Имя, ЧтениеXML.Значение);
		
	ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
		
		ЗаписьXML.ЗаписатьНачалоЭлемента(ЧтениеXML.Имя);
		
		Пока ЧтениеXML.ПрочитатьАтрибут() Цикл
			
			ЗаписьXML.ЗаписатьНачалоАтрибута(ЧтениеXML.Имя);
			ЗаписьXML.ЗаписатьТекст(ЧтениеXML.Значение);
			ЗаписьXML.ЗаписатьКонецАтрибута();
			
		КонецЦикла;
		
	ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
		
		ЗаписьXML.ЗаписатьКонецЭлемента();
		
	ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
		
		Если Текст = Неопределено Тогда
			ЗаписьXML.ЗаписатьТекст(ЧтениеXML.Значение);
		Иначе
			ЗаписьXML.ЗаписатьТекст(Текст);
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область РазборДокументаXMLНаОбласти

Процедура ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, ИмяПотока, КорневойТэг = "w:next", ЗаписатьОбъявление = Истина)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ СтруктураРазбораXML.БлокирующийПоток = ИмяПотока Тогда
		Возврат;
	КонецЕсли;
	
	Если НЕ СтруктураРазбораXML.ПотокиЗаписи.Свойство(ИмяПотока) Тогда
		СтруктураРазбораXML.ПотокиЗаписи.Вставить(ИмяПотока, Новый Структура("Поток, ЗаписьРазрешена, Уровень, ПотокЗакрыт, ТекстПотока, УровеньАбзаца"));
	КонецЕсли;
	
	Если НЕ СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ЗаписьРазрешена = Неопределено Тогда
		ВозобновитьЗаписьВПоток(СтруктураРазбораXML, ИмяПотока);
		Возврат;
	КонецЕсли;
	
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ЗаписьРазрешена  = Истина;
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].Поток            = ИнициализироватьЗаписьXML(КорневойТэг, , , ЗаписатьОбъявление);
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].Уровень          = ?(ПустаяСтрока(КорневойТэг), 0, 1);
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ПотокЗакрыт      = Ложь;
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ТекстПотока      = "";
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].УровеньАбзаца    = СтруктураРазбораXML.ТекущийУровеньАбзаца;
	
КонецПроцедуры

Процедура ОстановитьЗаписьВПоток(СтруктураРазбораXML, ИмяПотока)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ СтруктураРазбораXML.БлокирующийПоток = ИмяПотока Тогда
		Возврат;
	КонецЕсли;
	
	Если НЕ СтруктураРазбораXML.ПотокиЗаписи.Свойство(ИмяПотока) Тогда
		Возврат;
	КонецЕсли;
	
	Если СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ЗаписьРазрешена = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ЗаписьРазрешена = Ложь;
	
КонецПроцедуры

Процедура ВозобновитьЗаписьВПоток(СтруктураРазбораXML, ИмяПотока)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ СтруктураРазбораXML.БлокирующийПоток = ИмяПотока Тогда
		Возврат;
	КонецЕсли;
	
	Если НЕ СтруктураРазбораXML.ПотокиЗаписи.Свойство(ИмяПотока) Тогда
		Возврат;
	КонецЕсли;
	
	Если СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ЗаписьРазрешена = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ЗаписьРазрешена = Истина;
	
КонецПроцедуры

Процедура СброситьЗаписьВПоток(СтруктураРазбораXML, ИмяПотока)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ СтруктураРазбораXML.БлокирующийПоток = ИмяПотока Тогда
		Возврат;
	КонецЕсли;
	
	Если НЕ СтруктураРазбораXML.ПотокиЗаписи.Свойство(ИмяПотока) Тогда
		Возврат;
	КонецЕсли;
	
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ЗаписьРазрешена = Неопределено;
	
КонецПроцедуры

Функция ЗавершитьЗаписьВПоток(СтруктураРазбораXML, ИмяПотока)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ СтруктураРазбораXML.БлокирующийПоток = ИмяПотока Тогда
		Возврат "";
	КонецЕсли;
	
	Если НЕ СтруктураРазбораXML.ПотокиЗаписи.Свойство(ИмяПотока) Тогда
		Возврат "";
	КонецЕсли;
	
	Если СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ПотокЗакрыт = Истина Тогда
		Возврат "";
	КонецЕсли;
	
	Пока СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].Уровень > 0 Цикл
		СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].Поток.ЗаписатьКонецЭлемента();
		СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].Уровень = СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].Уровень - 1;
	КонецЦикла;
	
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ТекстПотока = СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].Поток.Закрыть();
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ЗаписьРазрешена = Неопределено;
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ПотокЗакрыт = Истина;
	
	Возврат СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ТекстПотока;
	
КонецФункции

Процедура ПеренестиЗаписьВПоток(СтруктураРазбораXML, ИмяПотокаИсточника, ИмяПотокаПриемника)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ СтруктураРазбораXML.БлокирующийПоток = ИмяПотокаПриемника Тогда
		Возврат;
	КонецЕсли;
	
	Если НЕ СтруктураРазбораXML.ПотокиЗаписи.Свойство(ИмяПотокаИсточника)
		 ИЛИ НЕ СтруктураРазбораXML.ПотокиЗаписи.Свойство(ИмяПотокаПриемника) Тогда
		Возврат;
	КонецЕсли;
	
	ЗавершитьЗаписьВПоток(СтруктураРазбораXML, ИмяПотокаИсточника);
	
	ТекстПотока = СтруктураРазбораXML.ПотокиЗаписи[ИмяПотокаИсточника].ТекстПотока;
	ТекстПотока = СтрЗаменить(ТекстПотока, "<w:next>", "<w:next " + СтруктураРазбораXML.АтрибутыXML + ">");
	
	ЧтениеXML = ИнициализироватьЧтениеXML(ТекстПотока);
	
	Пока ЧтениеXML.Прочитать() Цикл
		
		Если ЧтениеXML.Имя = "w:next" Тогда
			Продолжить;
		КонецЕсли;
		
		ЗаписатьЭлементXML(ЧтениеXML, СтруктураРазбораXML.ПотокиЗаписи[ИмяПотокаПриемника].Поток);
		
	КонецЦикла;
	
	ЧтениеXML.Закрыть();
	
КонецПроцедуры

Процедура ПеренестиОткрывающиеТэгиЗаписиВПоток(СтруктураРазбораXML, ИмяПотокаИсточника, ИмяПотокаПриемника, СтопТэг)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ СтруктураРазбораXML.БлокирующийПоток = ИмяПотокаПриемника Тогда
		Возврат;
	КонецЕсли;
	
	Если НЕ СтруктураРазбораXML.ПотокиЗаписи.Свойство(ИмяПотокаИсточника)
		 ИЛИ НЕ СтруктураРазбораXML.ПотокиЗаписи.Свойство(ИмяПотокаПриемника) Тогда
		Возврат;
	КонецЕсли;
	
	Если НЕ СтруктураРазбораXML.ПотокиЗаписи[ИмяПотокаИсточника].ПотокЗакрыт Тогда
		СтруктураРазбораXML.ПотокиЗаписи[ИмяПотокаИсточника].ЗаписьРазрешена = Ложь;
		СтруктураРазбораXML.ПотокиЗаписи[ИмяПотокаИсточника].Поток.ЗаписатьКонецЭлемента();
		СтруктураРазбораXML.ПотокиЗаписи[ИмяПотокаИсточника].ТекстПотока = СтруктураРазбораXML.ПотокиЗаписи[ИмяПотокаИсточника].Поток.Закрыть();
		СтруктураРазбораXML.ПотокиЗаписи[ИмяПотокаИсточника].ПотокЗакрыт = Истина;
	КонецЕсли;
	
	ТекстПотока = СтруктураРазбораXML.ПотокиЗаписи[ИмяПотокаИсточника].ТекстПотока;
	ТекстПотока = СтрЗаменить(ТекстПотока, "<w:next>", "<w:next " + СтруктураРазбораXML.АтрибутыXML + ">");
	
	ЧтениеXML = ИнициализироватьЧтениеXML(ТекстПотока);
	
	Пока ЧтениеXML.Прочитать() Цикл
		
		Если ЧтениеXML.Имя = "w:next" Тогда
			Продолжить;
		КонецЕсли;
		
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
			Продолжить;
		КонецЕсли;
		
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ЧтениеXML.Имя = СтопТэг Тогда
			Прервать;
		КонецЕсли;
		
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
			СтруктураРазбораXML.ПотокиЗаписи[ИмяПотокаПриемника].Уровень = СтруктураРазбораXML.ПотокиЗаписи[ИмяПотокаПриемника].Уровень + 1;
		КонецЕсли;
		
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
			СтруктураРазбораXML.ПотокиЗаписи[ИмяПотокаПриемника].Уровень = СтруктураРазбораXML.ПотокиЗаписи[ИмяПотокаПриемника].Уровень - 1;
		КонецЕсли;
		
		ЗаписатьЭлементXML(ЧтениеXML, СтруктураРазбораXML.ПотокиЗаписи[ИмяПотокаПриемника].Поток);
		
	КонецЦикла;
	
	ЧтениеXML.Закрыть();
	
КонецПроцедуры

Процедура ДобавитьАтрибутВПоток(СтруктураРазбораXML, ИмяПотока, ИмяАтрибута, ЗначениеАтрибута)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ СтруктураРазбораXML.БлокирующийПоток = ИмяПотока Тогда
		Возврат;
	КонецЕсли;
	
	Если НЕ СтруктураРазбораXML.ПотокиЗаписи.Свойство(ИмяПотока) Тогда
		Возврат;
	КонецЕсли;
	
	Если СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ПотокЗакрыт = Истина Тогда
		Возврат;
	КонецЕсли;
	
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].Поток.ЗаписатьНачалоАтрибута(ИмяАтрибута);
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].Поток.ЗаписатьТекст(ЗначениеАтрибута);
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].Поток.ЗаписатьКонецАтрибута();
	
КонецПроцедуры

Процедура ДобавитьТекстВПоток(СтруктураРазбораXML, ИмяПотока, Текст)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ СтруктураРазбораXML.БлокирующийПоток = ИмяПотока Тогда
		Возврат;
	КонецЕсли;
	
	Если НЕ СтруктураРазбораXML.ПотокиЗаписи.Свойство(ИмяПотока) Тогда
		Возврат;
	КонецЕсли;
	
	Если СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ПотокЗакрыт = Истина Тогда
		Возврат;
	КонецЕсли;
	
	СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].Поток.ЗаписатьТекст(Текст);
	
КонецПроцедуры

Процедура ЗакрытьЭлементыВПотоке(СтруктураРазбораXML, ИмяПотока, КоличествоЭлементов)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ СтруктураРазбораXML.БлокирующийПоток = ИмяПотока Тогда
		Возврат;
	КонецЕсли;
	
	Если НЕ СтруктураРазбораXML.ПотокиЗаписи.Свойство(ИмяПотока) Тогда
		Возврат;
	КонецЕсли;
	
	Если СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ПотокЗакрыт = Истина Тогда
		Возврат;
	КонецЕсли;
	
	Для Индекс = 1 По КоличествоЭлементов Цикл
		СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].Поток.ЗаписатьКонецЭлемента();
		СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].Уровень = СтруктураРазбораXML.ПотокиЗаписи.СтрокиПарам.Уровень - 1;
	КонецЦикла;
	
КонецПроцедуры

Функция ПотокАктивен(СтруктураРазбораXML, ИмяПотока)
	
	Если НЕ СтруктураРазбораXML.ПотокиЗаписи.Свойство(ИмяПотока) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Если СтруктураРазбораXML.ПотокиЗаписи[ИмяПотока].ЗаписьРазрешена = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат Истина;
	
КонецФункции

Процедура ЗаписатьИнструкциюОбработкиВПотоки(СтруктураРазбораXML, ЧтениеXML, ИмяПотока = "")
	
	Для Каждого ЭлементПотока Из СтруктураРазбораXML.ПотокиЗаписи Цикл
		
		Если СтруктураРазбораXML.ТекущийУровеньАбзаца <> ЭлементПотока.Значение.УровеньАбзаца Тогда
			Продолжить;
		КонецЕсли;
		
		Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ ЭлементПотока.Ключ = СтруктураРазбораXML.БлокирующийПоток Тогда
			Продолжить;
		КонецЕсли;
		
		Если НЕ ПустаяСтрока(ИмяПотока) И НЕ ЭлементПотока.Ключ = ИмяПотока Тогда
			Продолжить;
		КонецЕсли;
		
		Если НЕ ЭлементПотока.Значение.ЗаписьРазрешена = Истина Тогда
			Продолжить;
		КонецЕсли;
		
		ЭлементПотока.Значение.Поток.ЗаписатьИнструкциюОбработки(ЧтениеXML.Имя, ЧтениеXML.Значение);
		
	КонецЦикла;
	
КонецПроцедуры

Процедура ЗаписатьНачалоЭлементаВПотоки(СтруктураРазбораXML, ЧтениеXML, ИмяПотока = "")
	
	Для Каждого ЭлементПотока Из СтруктураРазбораXML.ПотокиЗаписи Цикл
		
		Если СтруктураРазбораXML.ТекущийУровеньАбзаца <> ЭлементПотока.Значение.УровеньАбзаца Тогда
			Продолжить;
		КонецЕсли;
		
		Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ ЭлементПотока.Ключ = СтруктураРазбораXML.БлокирующийПоток Тогда
			Продолжить;
		КонецЕсли;
		
		Если НЕ ПустаяСтрока(ИмяПотока) И НЕ ЭлементПотока.Ключ = ИмяПотока Тогда
			Продолжить;
		КонецЕсли;
		
		Если НЕ ЭлементПотока.Значение.ЗаписьРазрешена = Истина Тогда
			Продолжить;
		КонецЕсли;
		
		ЭлементПотока.Значение.Поток.ЗаписатьНачалоЭлемента(ЧтениеXML.Имя);
		ЭлементПотока.Значение.Уровень = ЭлементПотока.Значение.Уровень + 1;
		
	КонецЦикла;
	
КонецПроцедуры

Процедура ЗаписатьАтрибутВПотоки(СтруктураРазбораXML, ЧтениеXML, ИмяПотока = "", Знач Текст = Неопределено)
	
	Для Каждого ЭлементПотока Из СтруктураРазбораXML.ПотокиЗаписи Цикл
		
		Если СтруктураРазбораXML.ТекущийУровеньАбзаца <> ЭлементПотока.Значение.УровеньАбзаца Тогда
			Продолжить;
		КонецЕсли;
		
		Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ ЭлементПотока.Ключ = СтруктураРазбораXML.БлокирующийПоток Тогда
			Продолжить;
		КонецЕсли;
		
		Если НЕ ПустаяСтрока(ИмяПотока) И НЕ ЭлементПотока.Ключ = ИмяПотока Тогда
			Продолжить;
		КонецЕсли;
		
		Если НЕ ЭлементПотока.Значение.ЗаписьРазрешена = Истина Тогда
			Продолжить;
		КонецЕсли;
		
		Если Текст = Неопределено Тогда
			Текст = ЧтениеXML.Значение;
		КонецЕсли;
		
		ЭлементПотока.Значение.Поток.ЗаписатьНачалоАтрибута(ЧтениеXML.Имя);
		ЭлементПотока.Значение.Поток.ЗаписатьТекст(Текст);
		ЭлементПотока.Значение.Поток.ЗаписатьКонецАтрибута();
		
	КонецЦикла;
	
КонецПроцедуры

Процедура ЗаписатьКонецЭлементаВПотоки(СтруктураРазбораXML, ЧтениеXML, ИмяПотока = "")
	
	Для Каждого ЭлементПотока Из СтруктураРазбораXML.ПотокиЗаписи Цикл
		
		Если СтруктураРазбораXML.ТекущийУровеньАбзаца <> ЭлементПотока.Значение.УровеньАбзаца Тогда
			Продолжить;
		КонецЕсли;
		
		Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ ЭлементПотока.Ключ = СтруктураРазбораXML.БлокирующийПоток Тогда
			Продолжить;
		КонецЕсли;
		
		Если НЕ ПустаяСтрока(ИмяПотока) И НЕ ЭлементПотока.Ключ = ИмяПотока Тогда
			Продолжить;
		КонецЕсли;
		
		Если НЕ ЭлементПотока.Значение.ЗаписьРазрешена = Истина Тогда
			Продолжить;
		КонецЕсли;
		
		ЭлементПотока.Значение.Поток.ЗаписатьКонецЭлемента();
		ЭлементПотока.Значение.Уровень = ЭлементПотока.Значение.Уровень - 1;
		
	КонецЦикла;
	
КонецПроцедуры

Процедура ЗаписатьТекстВПотоки(СтруктураРазбораXML, ЧтениеXML, ИмяПотока = "", Знач Текст = Неопределено, УстановленАтрибутСохраненияПробелов = Неопределено)
	
	Для Каждого ЭлементПотока Из СтруктураРазбораXML.ПотокиЗаписи Цикл
		
		Если СтруктураРазбораXML.ТекущийУровеньАбзаца <> ЭлементПотока.Значение.УровеньАбзаца Тогда
			Продолжить;
		КонецЕсли;
		
		Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ ЭлементПотока.Ключ = СтруктураРазбораXML.БлокирующийПоток Тогда
			Продолжить;
		КонецЕсли;
		
		Если НЕ ПустаяСтрока(ИмяПотока) И НЕ ЭлементПотока.Ключ = ИмяПотока Тогда
			Продолжить;
		КонецЕсли;
		
		Если НЕ ЭлементПотока.Значение.ЗаписьРазрешена = Истина Тогда
			Продолжить;
		КонецЕсли;
		
		Если Текст = Неопределено Тогда
			Текст = ЧтениеXML.Значение;
		КонецЕсли;
		
		ЧислоСтрок = ?(ПустаяСтрока(Текст), 1, СтрЧислоСтрок(Текст));
		
		Если ЧислоСтрок > 1 Тогда
			
			Для Инд = 1 По ЧислоСтрок Цикл
				
				СтрокаТекста = СтрПолучитьСтроку(Текст, Инд);
				Если УстановленАтрибутСохраненияПробелов = Ложь Тогда
					ЭлементПотока.Значение.Поток.ЗаписатьАтрибут("xml:space", "preserve");
				КонецЕсли;
				ЭлементПотока.Значение.Поток.ЗаписатьТекст(СтрокаТекста);
				
				Если Инд < ЧислоСтрок Тогда
					ЭлементПотока.Значение.Поток.ЗаписатьКонецЭлемента();
					ЭлементПотока.Значение.Поток.ЗаписатьНачалоЭлемента("w:br");
					ЭлементПотока.Значение.Поток.ЗаписатьКонецЭлемента();
					ЭлементПотока.Значение.Поток.ЗаписатьНачалоЭлемента("w:t");
				КонецЕсли;
				
			КонецЦикла;
			
		Иначе
			Если УстановленАтрибутСохраненияПробелов = Ложь Тогда
				ЭлементПотока.Значение.Поток.ЗаписатьАтрибут("xml:space", "preserve");
			КонецЕсли;
			ЭлементПотока.Значение.Поток.ЗаписатьТекст(Текст);
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

Процедура ЗаписатьЭлементXMLВПоток(СтруктураРазбораXML, ЧтениеXML, СтруктураДокумента, УстановленАтрибутСохраненияПробелов = Неопределено)
	
	Если ЧтениеXML.ТипУзла = ТипУзлаXML.ИнструкцияОбработки Тогда
		
		ЗаписатьИнструкциюОбработкиВПотоки(СтруктураРазбораXML, ЧтениеXML);
		
	ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
		
		ИмяУзла = ЧтениеXML.Имя;
		
		ЗаписатьНачалоЭлементаВПотоки(СтруктураРазбораXML, ЧтениеXML);
		
		Пока ЧтениеXML.ПрочитатьАтрибут() Цикл
			
			Если ПустаяСтрока(СтруктураДокумента.ИдентификаторДокумента) И (Лев(ЧтениеXML.Имя, 6) = "w:rsid") Тогда
				СтруктураДокумента.ИдентификаторДокумента = ЧтениеXML.Значение;
			КонецЕсли;
			
			ЗначениеАтрибута = ЧтениеXML.Значение;
			
			Если Лев(ЧтениеXML.Имя, 4) = "r:id" И (ИмяУзла = "w:hyperlink") Тогда
				ДобавитьРазобраннуюСтрокуГиперссылка(СтруктураРазбораXML, СтруктураДокумента.ТаблицаСвязейКонтента.Найти(ЗначениеАтрибута, "ИДРесурса"));
			КонецЕсли;
			
			Если Лев(ЧтениеXML.Имя, 6) = "w:rsid" Тогда
				ЗначениеАтрибута = СтруктураДокумента.ИдентификаторДокумента;
			КонецЕсли;
			
			УстановленАтрибутСохраненияПробелов = ЧтениеXML.Имя = "xml:space";
			
			ЗаписатьАтрибутВПотоки(СтруктураРазбораXML, ЧтениеXML,, ЗначениеАтрибута);
			
			Если ИмяУзла = "w:document" ИЛИ ИмяУзла = "w:ftr" ИЛИ ИмяУзла = "w:hdr" Тогда
				СтруктураРазбораXML.АтрибутыXML = СтруктураРазбораXML.АтрибутыXML + " " + ЧтениеXML.Имя + "=""" + ЧтениеXML.Значение + """";
			КонецЕсли;
			
		КонецЦикла;
		
	ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
		
		ЗаписатьКонецЭлементаВПотоки(СтруктураРазбораXML, ЧтениеXML);
		
	ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
		
		Если СтруктураРазбораXML.Свойство("СтатусТэга1С") Тогда
			АнализироватьПараметрыВСтроке(ЧтениеXML.Значение, СтруктураРазбораXML);
		КонецЕсли;
		
		ЗаписатьТекстВПотоки(СтруктураРазбораXML, ЧтениеXML);
		
	КонецЕсли;
	
КонецПроцедуры



Функция ЧтениеНачалаЛюбогоБлокаКромеПараграфа(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И НЕ ЧтениеXML.Имя = "w:p";
	
КонецФункции

Функция ЧтениеКонцаЛюбогоБлокаКромеПараграфа(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И НЕ ЧтениеXML.Имя = "w:p";
	
КонецФункции

Функция ЧтениеНачалаТелаДокумента(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "w:body";
	
КонецФункции

Функция ЧтениеНачалаТелаКолонтитула(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И (ЧтениеXML.Имя = "w:ftr" ИЛИ ЧтениеXML.Имя = "w:hdr");
	
КонецФункции

Функция ЧтениеНачалаПараграфа(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "w:p";
	
КонецФункции

Функция ЧтениеКонцаПараграфа(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ЧтениеXML.Имя = "w:p";
	
КонецФункции

Функция ЧтениеНачалаСтроки(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "w:r";
	
КонецФункции

Функция ЧтениеКонцаСтроки(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ЧтениеXML.Имя = "w:r";
	
КонецФункции

Функция ЧтениеНачалаТекстаСтроки(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "w:t";
	
КонецФункции

Функция ЧтениеКонцаТекстаСтроки(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ЧтениеXML.Имя = "w:t";
	
КонецФункции

Функция ЧтениеНачалаТаблицы(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "w:tbl";
	
КонецФункции

Функция ЧтениеКонцаТаблицы(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ЧтениеXML.Имя = "w:tbl";
	
КонецФункции

Функция ЧтениеНачалаШириныТаблицы(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "w:tblW";
	
КонецФункции

Функция ЧтениеНачалаШириныКлеткиТаблицы(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "w:tcW";
	
КонецФункции

Функция ЧтениеНачалаКлеткиТаблицы(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "w:tc";
	
КонецФункции

Функция ЧтениеКонцаКлеткиТаблицы(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ЧтениеXML.Имя = "w:tc";
	
КонецФункции

Функция ЧтениеНачалаРаздела(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ СтруктураРазбораXML.БлокирующийПоток = "Раздел" Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "w:sectPr";
	
КонецФункции

Функция ЧтениеКонцаРаздела(СтруктураРазбораXML, ЧтениеXML)
	
	Если Не ПустаяСтрока(СтруктураРазбораXML.БлокирующийПоток) И НЕ СтруктураРазбораXML.БлокирующийПоток = "Раздел" Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ЧтениеXML.Имя = "w:sectPr";
	
КонецФункции

Функция ИнициализироватьРазборXML()
	
	Результат = Новый Структура;
	Результат.Вставить("ПотокиЗаписи",      Новый Структура);
	Результат.Вставить("АтрибутыXML",       "");
	Результат.Вставить("ИмяОбласти",        "");
	Результат.Вставить("СтатусОбласти",     0);
	Результат.Вставить("НомерРаздела",      1);
	Результат.Вставить("БлокирующийПоток",  "");
	Результат.Вставить("РазобранныеСтроки", Новый Массив);
	Результат.Вставить("ИмяПотокаФормата",  "");
	Результат.Вставить("ТекущийУровеньАбзаца", "0");
	Результат.Вставить("Гиперссылки",       Новый Массив);
	
	Возврат Результат;
	
КонецФункции

// Возвращаемое значение:
//  Структура:
//   * ИДРесурса 
//   * ИмяПараметра 
//   * Ссылка 
//
Функция СтруктураГиперссылки()
	Структура = Новый Структура("ИДРесурса,ИмяПараметра,Ссылка");
	Возврат Структура;
КонецФункции

Функция ТипыКолонтитулов()
	
	Результат = Новый Соответствие;
	Результат.Вставить("w:headerReference_even",    "ВерхнийЧетныйКолонтитул");
	Результат.Вставить("w:footerReference_even",    "НижнийЧетныйКолонтитул");
	Результат.Вставить("w:headerReference_first",   "ВерхнийТитульныйКолонтитул");
	Результат.Вставить("w:footerReference_first",   "НижнийТитульныйКолонтитул");
	Результат.Вставить("w:headerReference_default", "ВерхнийКолонтитул");
	Результат.Вставить("w:footerReference_default", "НижнийКолонтитул");
	
	Возврат Результат;
	
КонецФункции

Процедура СброситьСтатусыТэгов1С(СтруктураРазбораXML, СброситьПотокиШаблоннойСтроки = Ложь)
	
	СтруктураРазбораXML.Вставить("СтатусТэга1С",     0);
	СтруктураРазбораXML.Вставить("ТипТэга1С",        0);
	СтруктураРазбораXML.Вставить("ИмяТэга1С",        "");
	СтруктураРазбораXML.Вставить("ПолноеИмяТэга1С",  "");
	СтруктураРазбораXML.Вставить("ТекстДоТэга1С",    "");
	СтруктураРазбораXML.Вставить("ТекстПослеТэга1С", "");
	
	Если СброситьПотокиШаблоннойСтроки Тогда
		СброситьПотокиШаблоннойСтроки(СтруктураРазбораXML)
	КонецЕсли;
	
КонецПроцедуры

Процедура ДобавитьРазобраннуюСтроку(СтруктураРазбораXML, Строка, СтатусТэга1С = 0, ИмяОбласти = "", ПотокФормата = "")
	
	СтруктураСтроки = Новый Структура;
	СтруктураСтроки.Вставить("СтатусТэга1С", СтатусТэга1С);
	СтруктураСтроки.Вставить("ИмяОбласти",   ИмяОбласти);
	СтруктураСтроки.Вставить("Текст",        Строка);
	СтруктураСтроки.Вставить("ПотокФормата", ПотокФормата);
	
	СтруктураРазбораXML.РазобранныеСтроки.Добавить(СтруктураСтроки);
	
КонецПроцедуры

Процедура ДобавитьРазобраннуюСтрокуГиперссылка(СтруктураРазбораXML, СтрокаРесурса)
	
	СтрокаСсылка = РаскодироватьСтроку(СтрокаРесурса.ИмяРесурса, СпособКодированияСтроки.КодировкаURL);
	
	ПараметрыИзТекста = Новый Массив;
	ВыделитьПараметры(ПараметрыИзТекста, СтрокаСсылка);
	
	Для Каждого ПараметрТекст Из ПараметрыИзТекста Цикл
		СтруктураГиперссылки = СтруктураГиперссылки();
		СтруктураГиперссылки.ИДРесурса = СтрокаРесурса.ИдРесурса;
		СтруктураГиперссылки.ИмяПараметра = ПараметрТекст;
		СтруктураГиперссылки.Ссылка = СтрокаСсылка;
		СтруктураРазбораXML.Гиперссылки.Добавить(СтруктураГиперссылки);
	КонецЦикла;
	
КонецПроцедуры

Процедура СформироватьРазобранныеСтроки(СтруктураРазбораXML)
	
	Если СтруктураРазбораXML.СтатусТэга1С = 7 И СтруктураРазбораXML.ТипТэга1С = 0
		 ИЛИ СтруктураРазбораXML.СтатусТэга1С = 3 И СтруктураРазбораXML.ТипТэга1С = 1 И НЕ ПустаяСтрока(СтруктураРазбораXML.ИмяОбласти)
		 ИЛИ СтруктураРазбораXML.СтатусТэга1С = 7 И СтруктураРазбораXML.ТипТэга1С = 1 И НЕ СтруктураРазбораXML.ИмяТэга1С = СтруктураРазбораXML.ИмяОбласти Тогда
		
		СброситьСтатусыТэгов1С(СтруктураРазбораXML, Истина);
		Возврат;
	КонецЕсли;
	
	Если НЕ СтруктураРазбораXML.ТекстДоТэга1С = "" Тогда
		ДобавитьРазобраннуюСтроку(СтруктураРазбораXML, СтруктураРазбораXML.ТекстДоТэга1С,,,"ФорматТекстаДо");
	КонецЕсли;
	
	Если НЕ СтруктураРазбораXML.ПолноеИмяТэга1С = "" Тогда
		Если СтруктураРазбораXML.СтатусТэга1С = 3 ИЛИ СтруктураРазбораXML.СтатусТэга1С = 7 Тогда
			СтруктураРазбораXML.ПолноеИмяТэга1С = СтрЗаменить(СтруктураРазбораXML.ПолноеИмяТэга1С, " ", "");
			СтруктураРазбораXML.ПолноеИмяТэга1С = СтрЗаменить(СтруктураРазбораXML.ПолноеИмяТэга1С, "{v8", "{v8 ");
			СтруктураРазбораXML.ПолноеИмяТэга1С = СтрЗаменить(СтруктураРазбораXML.ПолноеИмяТэга1С, "{/v8", "{/v8 ");
		КонецЕсли;
		ДобавитьРазобраннуюСтроку(СтруктураРазбораXML, СтруктураРазбораXML.ПолноеИмяТэга1С, ?(СтруктураРазбораXML.ТипТэга1С = 1, СтруктураРазбораXML.СтатусТэга1С, 0), ?(СтруктураРазбораXML.ТипТэга1С = 1, СтруктураРазбораXML.ИмяТэга1С, ""),"ФорматТэга1С");
	КонецЕсли;
	
	Если НЕ СтруктураРазбораXML.ТекстПослеТэга1С = "" Тогда
		ДобавитьРазобраннуюСтроку(СтруктураРазбораXML, СтруктураРазбораXML.ТекстПослеТэга1С,,,"ФорматТекстаПосле");
	КонецЕсли;
	
	СброситьСтатусыТэгов1С(СтруктураРазбораXML);
	
КонецПроцедуры

Процедура ОчиститьРазобранныеСтроки(СтруктураРазбораXML)
	
	СтруктураРазбораXML.РазобранныеСтроки.Очистить();
	
КонецПроцедуры

Процедура ОчиститьГиперссылки(СтруктураРазбораXML)
	
	СтруктураРазбораXML.Гиперссылки.Очистить();
	
КонецПроцедуры

Процедура ИнициализироватьПотокиШаблоннойСтроки(СтруктураРазбораXML)
	
	Если СтруктураРазбораXML.СтатусТэга1С = 1 ИЛИ СтруктураРазбораXML.СтатусТэга1С = 5 Тогда
		
		Если НЕ ПотокАктивен(СтруктураРазбораXML, "ФорматТекстаДо") Тогда
			ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "ФорматТекстаДо");
			ПеренестиЗаписьВПоток(СтруктураРазбораXML, СтруктураРазбораXML.ИмяПотокаФормата, "ФорматТекстаДо");
			ОстановитьЗаписьВПоток(СтруктураРазбораXML, "ФорматТекстаДо");
		КонецЕсли;
		
	КонецЕсли;
	
	Если СтруктураРазбораXML.СтатусТэга1С = 2 ИЛИ СтруктураРазбораXML.СтатусТэга1С = 6 Тогда
		
		Если НЕ ПотокАктивен(СтруктураРазбораXML, "ФорматТекстаДо") Тогда
			ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "ФорматТекстаДо");
			ПеренестиЗаписьВПоток(СтруктураРазбораXML, СтруктураРазбораXML.ИмяПотокаФормата, "ФорматТекстаДо");
			ОстановитьЗаписьВПоток(СтруктураРазбораXML, "ФорматТекстаДо");
		КонецЕсли;
		
		Если НЕ ПотокАктивен(СтруктураРазбораXML, "ФорматТэга1С") Тогда
			ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "ФорматТэга1С");
			ПеренестиЗаписьВПоток(СтруктураРазбораXML, СтруктураРазбораXML.ИмяПотокаФормата, "ФорматТэга1С");
			ОстановитьЗаписьВПоток(СтруктураРазбораXML, "ФорматТэга1С");
		КонецЕсли;
		
	КонецЕсли;
	
	Если СтруктураРазбораXML.СтатусТэга1С = 3 ИЛИ СтруктураРазбораXML.СтатусТэга1С = 7 Тогда
		
		Если НЕ ПотокАктивен(СтруктураРазбораXML, "ФорматТекстаДо") Тогда
			ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "ФорматТекстаДо");
			ПеренестиЗаписьВПоток(СтруктураРазбораXML, СтруктураРазбораXML.ИмяПотокаФормата, "ФорматТекстаДо");
			ОстановитьЗаписьВПоток(СтруктураРазбораXML, "ФорматТекстаДо");
		КонецЕсли;
		
		Если НЕ ПотокАктивен(СтруктураРазбораXML, "ФорматТэга1С") Тогда
			ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "ФорматТэга1С");
			ПеренестиЗаписьВПоток(СтруктураРазбораXML, СтруктураРазбораXML.ИмяПотокаФормата, "ФорматТэга1С");
			ОстановитьЗаписьВПоток(СтруктураРазбораXML, "ФорматТэга1С");
		КонецЕсли;
		
		Если НЕ ПотокАктивен(СтруктураРазбораXML, "ФорматТекстаПосле") Тогда
			ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "ФорматТекстаПосле");
			ПеренестиЗаписьВПоток(СтруктураРазбораXML, СтруктураРазбораXML.ИмяПотокаФормата, "ФорматТекстаПосле");
			ОстановитьЗаписьВПоток(СтруктураРазбораXML, "ФорматТекстаПосле");
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

Процедура СброситьПотокиШаблоннойСтроки(СтруктураРазбораXML)
	
	СброситьЗаписьВПоток(СтруктураРазбораXML, "ФорматТекстаДо");
	СброситьЗаписьВПоток(СтруктураРазбораXML, "ФорматТэга1С");
	СброситьЗаписьВПоток(СтруктураРазбораXML, "ФорматТекстаПосле");
	
КонецПроцедуры

Процедура РазбитьТекстШаблонаНаОбласти(ЧтениеXML, СтруктураДокумента, ПараметрыАнализа)
	
	УровеньТэгаБлок       = -1;
	УровеньТэгаОбласть    = -1;
	УровеньАбзаца         = "0";
	ТекущийУровень        = 0;
	ПропуститьТэг         = Ложь;
	ТекстРаздела          = "";
	
	ИдентификаторЗакладкиЭЦП 		= "";
	ТекстБуфераЗакладок				= "";
	СоответствиеАтрибутовЗакладок 	= Новый Соответствие();
		
	СтруктураРазбораXML = ИнициализироватьРазборXML();
	
	СброситьСтатусыТэгов1С(СтруктураРазбораXML);
	
	ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "Заголовок", "");
	
	Если ПараметрыАнализа.ТипАнализа <> 1 Тогда
		ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "Блок", "");
		УровеньТэгаБлок = 0;
	КонецЕсли;
	
	Пока ЧтениеXML.Прочитать() Цикл
		
		// тег описания пространства имен во временном xml
		Если ЧтениеXML.Имя = "w:next" Тогда
			Продолжить;
		КонецЕсли;
		
		Если (ЧтениеXML.Имя = "w:bookmarkStart" ИЛИ ЧтениеXML.Имя = "w:bookmarkEnd") Тогда
			
			Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
				БуферЗакладок 			 = ИнициализироватьЗаписьXML("");
				БуферЗакладок.ЗаписатьТекущий(ЧтениеXML);
			
				ТекстБуфераЗакладок = БуферЗакладок.Закрыть();
				
				ЧтениеXMLЗакладок = ИнициализироватьЧтениеXML(ТекстБуфераЗакладок);
				ЧтениеXMLЗакладок.Прочитать();
				
				СоответствиеАтрибутовЗакладок = ПолучитьАтрибуты(ЧтениеXMLЗакладок);
			КонецЕсли;
			
			Если СоответствиеАтрибутовЗакладок.Получить("w:name") <> "V8DSStamp" И ИдентификаторЗакладкиЭЦП <> СоответствиеАтрибутовЗакладок.Получить("w:id") Тогда
			
				Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
					ПропуститьТэг = Истина;
				ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
					ПропуститьТэг = Ложь;
				КонецЕсли;
				
				Продолжить;
				
			Иначе
							
				ИдентификаторЗакладкиЭЦП = СоответствиеАтрибутовЗакладок.Получить("w:id");
			КонецЕсли;
			
		КонецЕсли;
		
		Если ПропуститьТэг Тогда
			Продолжить;
		КонецЕсли;
		
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
			ТекущийУровень = ТекущийУровень + 1;
		КонецЕсли;
		
		Если ЧтениеНачалаРаздела(СтруктураРазбораXML, ЧтениеXML) Тогда
			СтруктураРазбораXML.БлокирующийПоток = "Раздел";
			ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "Раздел", "", Ложь);
			ПеренестиОткрывающиеТэгиЗаписиВПоток(СтруктураРазбораXML, "Заголовок", "Раздел", "w:body");
		КонецЕсли;
		
		Если ЧтениеНачалаЛюбогоБлокаКромеПараграфа(СтруктураРазбораXML, ЧтениеXML) И ТекущийУровень = УровеньТэгаБлок Тогда
			ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "Блок");
		КонецЕсли;
		
		Если ЧтениеНачалаПараграфа(СтруктураРазбораXML, ЧтениеXML) Тогда
			УровеньАбзаца = Формат(Число(УровеньАбзаца) + 1, "ЧН=0; ЧГ=0");
			СтруктураРазбораXML.ТекущийУровеньАбзаца = УровеньАбзаца;
			
			СброситьСтатусыТэгов1С(СтруктураРазбораXML, Истина);
			ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "Абзац" + УровеньАбзаца);
			ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "Строки" + УровеньАбзаца);
			ОстановитьЗаписьВПоток(СтруктураРазбораXML, "Строки" + УровеньАбзаца);
		КонецЕсли;
		
		Если ЧтениеКонцаПараграфа(СтруктураРазбораXML, ЧтениеXML) Тогда
			ВозобновитьЗаписьВПоток(СтруктураРазбораXML, "Абзац" + УровеньАбзаца);
		КонецЕсли;
		
		Если ЧтениеНачалаСтроки(СтруктураРазбораXML, ЧтениеXML) Тогда
			ВозобновитьЗаписьВПоток(СтруктураРазбораXML, "Строки" + УровеньАбзаца);
			ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "СтрокаПарам" + УровеньАбзаца);
			ОстановитьЗаписьВПоток(СтруктураРазбораXML, "Абзац" + УровеньАбзаца);
			СтруктураРазбораXML.ИмяПотокаФормата = "СтрокаПарам" + УровеньАбзаца;
		КонецЕсли;
		
		ЧтениеНачалаТекстаСтроки = ЧтениеНачалаТекстаСтроки(СтруктураРазбораXML, ЧтениеXML);
		
		ЗавершитьЗаписьВЗаголовок = ЧтениеНачалаТелаДокумента(СтруктураРазбораXML, ЧтениеXML) ИЛИ ЧтениеНачалаТелаКолонтитула(СтруктураРазбораXML, ЧтениеXML);
		
		ЗаписатьЭлементXMLВПоток(СтруктураРазбораXML, ЧтениеXML, СтруктураДокумента);
		
		Если ЧтениеНачалаТекстаСтроки Тогда
			ЗавершитьЗаписьВПоток(СтруктураРазбораXML, "СтрокаПарам" + УровеньАбзаца);
		КонецЕсли;
		
		Если ЗавершитьЗаписьВЗаголовок Тогда
			УровеньТэгаБлок    = СтруктураРазбораXML.ПотокиЗаписи.Заголовок.Уровень + 1;
			УровеньТэгаОбласть = СтруктураРазбораXML.ПотокиЗаписи.Заголовок.Уровень + 2;
			
			ЗавершитьЗаписьВПоток(СтруктураРазбораXML, "Заголовок");
		КонецЕсли;
		
		Если ЧтениеКонцаСтроки(СтруктураРазбораXML, ЧтениеXML) Тогда
			Если СтруктураРазбораXML.СтатусТэга1С = 0 И СтруктураРазбораXML.РазобранныеСтроки.Количество() = 0 Тогда
				ПеренестиЗаписьВПоток(СтруктураРазбораXML, "Строки" + УровеньАбзаца, "Абзац" + УровеньАбзаца);
			ИначеЕсли СтруктураРазбораXML.РазобранныеСтроки.Количество() > 0 Тогда
				ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "СтрокиПарам");
				
				КоличествоСтрок = 0;
				
				Для Каждого ЭлементСтроки Из СтруктураРазбораXML.РазобранныеСтроки Цикл
					
					Если ПараметрыАнализа.ТипАнализа = 1 И ТекущийУровень = УровеньТэгаОбласть И ЭлементСтроки.СтатусТэга1С = 3 И ПустаяСтрока(СтруктураРазбораXML.ИмяОбласти) Тогда
						
						СтруктураРазбораXML.ИмяОбласти = ЭлементСтроки.ИмяОбласти;
						СтруктураРазбораXML.СтатусОбласти = 0;
						КоличествоСтрок = 0;
						
						ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "Область", "");
						ПеренестиОткрывающиеТэгиЗаписиВПоток(СтруктураРазбораXML, "Заголовок", "Область", "w:body");
						ОстановитьЗаписьВПоток(СтруктураРазбораXML, "Область");
						СброситьЗаписьВПоток(СтруктураРазбораXML, "СтрокиПарам");
						ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "СтрокиПарам");
						
						Прервать;
						
					ИначеЕсли ПараметрыАнализа.ТипАнализа = 1 И ТекущийУровень = УровеньТэгаОбласть И ЭлементСтроки.СтатусТэга1С = 7 И СтруктураРазбораXML.ИмяОбласти = ЭлементСтроки.ИмяОбласти Тогда
						
						ТекстОбласти = ЗавершитьЗаписьВПоток(СтруктураРазбораXML, "Область");
						
						СтруктураОбласти = ОбластьДокумента();
						СтруктураОбласти.Имя          = СтруктураРазбораXML.ИмяОбласти;
						СтруктураОбласти.Текст        = ТекстОбласти;
						СтруктураОбласти.НомерРаздела = СтруктураРазбораXML.НомерРаздела;
						СтруктураОбласти.Гиперссылки  = ОбщегоНазначения.СкопироватьРекурсивно(СтруктураРазбораXML.Гиперссылки);
						
						ОчиститьГиперссылки(СтруктураРазбораXML);
						
						ДобавитьВСтруктуруДокументаОбластьДокумента(СтруктураДокумента, СтруктураОбласти);
						
						СтруктураРазбораXML.ИмяОбласти = "";
						СтруктураРазбораXML.СтатусОбласти = 0;
						
						Прервать;
						
					КонецЕсли;
					
					КоличествоСтрок = КоличествоСтрок + 1;
					
					ЗавершитьЗаписьВПоток(СтруктураРазбораXML, ЭлементСтроки.ПотокФормата);
					
					ИмеетсяАтрибутПробела = СтрНайти(СтруктураРазбораXML.ПотокиЗаписи[ЭлементСтроки.ПотокФормата].ТекстПотока, "w:t xml:space", НаправлениеПоиска.СКонца) > 0;
					
					ПеренестиОткрывающиеТэгиЗаписиВПоток(СтруктураРазбораXML, ЭлементСтроки.ПотокФормата, "СтрокиПарам", "w:t");
					
					Если НЕ ИмеетсяАтрибутПробела И (ПустаяСтрока(Лев(ЭлементСтроки.Текст, 1)) ИЛИ ПустаяСтрока(Прав(ЭлементСтроки.Текст, 1))) Тогда
						ДобавитьАтрибутВПоток(СтруктураРазбораXML, "СтрокиПарам", "xml:space", "preserve");
					КонецЕсли;
					ДобавитьТекстВПоток(СтруктураРазбораXML, "СтрокиПарам", ЭлементСтроки.Текст);
					ЗакрытьЭлементыВПотоке(СтруктураРазбораXML, "СтрокиПарам", 2);
					
				КонецЦикла;
				
				Если КоличествоСтрок > 0 Тогда
					ПеренестиЗаписьВПоток(СтруктураРазбораXML, "СтрокиПарам", "Абзац" + УровеньАбзаца);
				КонецЕсли;
				
				СброситьЗаписьВПоток(СтруктураРазбораXML, "СтрокиПарам");
				СброситьПотокиШаблоннойСтроки(СтруктураРазбораXML);
				ОчиститьРазобранныеСтроки(СтруктураРазбораXML);
			КонецЕсли;
			
			СброситьЗаписьВПоток(СтруктураРазбораXML, "СтрокаПарам" + УровеньАбзаца);
			
			Если СтруктураРазбораXML.СтатусТэга1С = 0 И СтруктураРазбораXML.РазобранныеСтроки.Количество() = 0 ИЛИ СтруктураРазбораXML.РазобранныеСтроки.Количество() > 0 Тогда
				СброситьЗаписьВПоток(СтруктураРазбораXML, "Строки" + УровеньАбзаца);
				ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "Строки" + УровеньАбзаца);
				ОстановитьЗаписьВПоток(СтруктураРазбораXML, "Строки" + УровеньАбзаца);
			КонецЕсли;
		КонецЕсли;
		
		Если ЧтениеКонцаПараграфа(СтруктураРазбораXML, ЧтениеXML) Тогда
			Если НЕ СтруктураРазбораXML.СтатусТэга1С = 0 Тогда
				СброситьСтатусыТэгов1С(СтруктураРазбораXML, Истина);
			КонецЕсли;
			
			Если Число(УровеньАбзаца) > 1 Тогда
				ПотокПереноса = "Строки" + Формат(Число(УровеньАбзаца) - 1, "ЧН=0; ЧГ=0");
			ИначеЕсли ТекущийУровень = УровеньТэгаБлок И ПараметрыАнализа.ТипАнализа = 1 Тогда
				ПотокПереноса = "Область";
			Иначе
				ПотокПереноса = "Блок";
			КонецЕсли;
			
			Если ПараметрыАнализа.ТипАнализа <> 1
				 ИЛИ НЕ ПустаяСтрока(СтруктураРазбораXML.ИмяОбласти) И СтруктураРазбораXML.СтатусОбласти = 1 Тогда
				ПеренестиЗаписьВПоток(СтруктураРазбораXML, "Абзац" + УровеньАбзаца, ПотокПереноса);
			КонецЕсли;
			
			СброситьЗаписьВПоток(СтруктураРазбораXML, "Абзац" + УровеньАбзаца);
			СброситьЗаписьВПоток(СтруктураРазбораXML, "Строки" + УровеньАбзаца);
			
			Если НЕ ПустаяСтрока(СтруктураРазбораXML.ИмяОбласти) И СтруктураРазбораXML.СтатусОбласти = 0 Тогда
				СтруктураРазбораXML.СтатусОбласти = 1;
			КонецЕсли;
			
			УровеньАбзаца = Формат(Число(УровеньАбзаца) - 1, "ЧН=0; ЧГ=0");
			СтруктураРазбораXML.ТекущийУровеньАбзаца = УровеньАбзаца;
			СтруктураРазбораXML.ИмяПотокаФормата = "СтрокаПарам" + УровеньАбзаца;
		КонецЕсли;
		
		Если ЧтениеКонцаЛюбогоБлокаКромеПараграфа(СтруктураРазбораXML, ЧтениеXML) И ТекущийУровень = УровеньТэгаБлок Тогда
			Если Не ПустаяСтрока(СтруктураРазбораXML.ИмяОбласти) И СтруктураРазбораXML.СтатусОбласти = 1 Тогда
				ПеренестиЗаписьВПоток(СтруктураРазбораXML, "Блок", "Область");
			КонецЕсли;
			СброситьЗаписьВПоток(СтруктураРазбораXML, "Блок");
		КонецЕсли;
		
		Если ЧтениеКонцаРаздела(СтруктураРазбораXML, ЧтениеXML) Тогда
			ТекстРаздела = ЗавершитьЗаписьВПоток(СтруктураРазбораXML, "Раздел");
			СтруктураРазбораXML.БлокирующийПоток = "";
		КонецЕсли;
		
		Если НЕ ПустаяСтрока(ТекстРаздела) И ТекущийУровень = УровеньТэгаБлок Тогда
			Если СтруктураРазбораXML.СтатусОбласти = 0 Тогда
				СтруктураРаздела = ОбластьРаздела();
				СтруктураРаздела.Текст = ТекстРаздела;
				СтруктураРаздела.Номер = СтруктураРазбораXML.НомерРаздела;
				ДобавитьВСтруктуруДокументаРаздел(СтруктураДокумента, СтруктураРаздела);
				СтруктураРазбораXML.НомерРаздела = СтруктураРазбораXML.НомерРаздела + 1;
			КонецЕсли;
			ТекстРаздела = "";
		КонецЕсли;
		
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
			ТекущийУровень = ТекущийУровень - 1;
		КонецЕсли;
		
	КонецЦикла;
	
	Если ПараметрыАнализа.ТипАнализа = 2 ИЛИ ПараметрыАнализа.ТипАнализа = 3 Тогда
		ТекстОбласти = ЗавершитьЗаписьВПоток(СтруктураРазбораXML, "Блок");
		ПараметрыАнализа.СтруктураАнализа.Текст  = ТекстОбласти;
	КонецЕсли;
	
	Если ПараметрыАнализа.ТипАнализа = 1  Тогда
		ИнициализироватьЗаписьВПоток(СтруктураРазбораXML, "Абзац", "");
		ПеренестиОткрывающиеТэгиЗаписиВПоток(СтруктураРазбораXML, "Заголовок", "Абзац", "w:body");
		
		ТекстРазрыва = "<w:p w:rsidRDefault=""" + СтруктураДокумента.ИдентификаторДокумента + """ w:rsidR=""" + СтруктураДокумента.ИдентификаторДокумента + """></w:p>";
		СтруктураРазбораXML.ПотокиЗаписи.Абзац.Поток.ЗаписатьБезОбработки(ТекстРазрыва);
		
		ТекстОбласти = ЗавершитьЗаписьВПоток(СтруктураРазбораXML, "Абзац");
		
		СтруктураОбласти = ОбластьДокумента();
		СтруктураОбласти.Имя          = "Абзац";
		СтруктураОбласти.Текст        = ТекстОбласти;
		СтруктураОбласти.НомерРаздела = 0;
		ДобавитьВСтруктуруДокументаОбластьДокумента(СтруктураДокумента, СтруктураОбласти);
	КонецЕсли;
	
КонецПроцедуры

Процедура АнализироватьПараметрыВСтроке(Знач Строка, СтруктураРазбораXML)
	
	// 1 - начало тэга {v8
	// 2 - начало параметра тэга {v8
	// 3 - конец параметра тэга {v8
	
	// 5 - начало тэга {/v8
	// 6 - начало параметра тэга {/v8
	// 7 - конец параметра тэга {/v8
	
	ПризнакНачалаТэга1С = "{v8 ";
	ПризнакКонцаТэга1С  = "{/v8 ";
	
	ДлинаСтрокиТэга1С       = СтрДлина(СтруктураРазбораXML.ПолноеИмяТэга1С);
	ДлинаСтроки             = СтрДлина(Строка);
	
	Для ф = 1 По ДлинаСтроки Цикл
		
		Символ      = Сред(Строка, ф, 1);
		КодСимвола  = КодСимвола(Символ);
		
		Если Символ = "{" И (СтруктураРазбораXML.СтатусТэга1С = 3 ИЛИ СтруктураРазбораXML.СтатусТэга1С = 7) Тогда
			ИнициализироватьПотокиШаблоннойСтроки(СтруктураРазбораXML);
			СформироватьРазобранныеСтроки(СтруктураРазбораXML);
			ДлинаСтрокиТэга1С = 0;
		КонецЕсли;
		
		Если ДлинаСтрокиТэга1С + 1 <= СтрДлина(ПризнакНачалаТэга1С) И Лев(ПризнакНачалаТэга1С, ДлинаСтрокиТэга1С + 1) = СтруктураРазбораXML.ПолноеИмяТэга1С + Символ Тогда
			
			СтруктураРазбораXML.СтатусТэга1С = 1;
			СтруктураРазбораXML.ПолноеИмяТэга1С = СтруктураРазбораXML.ПолноеИмяТэга1С + Символ;
			ДлинаСтрокиТэга1С = ДлинаСтрокиТэга1С + 1;
			Продолжить;
			
		ИначеЕсли ДлинаСтрокиТэга1С <= СтрДлина(ПризнакКонцаТэга1С) И Лев(ПризнакКонцаТэга1С, ДлинаСтрокиТэга1С + 1) = СтруктураРазбораXML.ПолноеИмяТэга1С + Символ Тогда
			
			СтруктураРазбораXML.СтатусТэга1С = 5;
			СтруктураРазбораXML.ПолноеИмяТэга1С = СтруктураРазбораXML.ПолноеИмяТэга1С + Символ;
			ДлинаСтрокиТэга1С = ДлинаСтрокиТэга1С + 1;
			Продолжить;
			
		КонецЕсли;
		
		Если СтруктураРазбораXML.СтатусТэга1С = 0 И СтрНачинаетсяС(СтруктураРазбораXML.ПолноеИмяТэга1С, ПризнакНачалаТэга1С) Тогда
			СтруктураРазбораXML.СтатусТэга1С = 1;
		ИначеЕсли СтруктураРазбораXML.СтатусТэга1С = 0 И СтрНачинаетсяС(СтруктураРазбораXML.ПолноеИмяТэга1С, ПризнакКонцаТэга1С) Тогда
			СтруктураРазбораXML.СтатусТэга1С = 5;
		КонецЕсли;
		
		Если СтруктураРазбораXML.СтатусТэга1С = 1 И НЕ СтрНачинаетсяС(СтруктураРазбораXML.ПолноеИмяТэга1С, ПризнакНачалаТэга1С)
			 ИЛИ СтруктураРазбораXML.СтатусТэга1С = 5 И НЕ СтрНачинаетсяС(СтруктураРазбораXML.ПолноеИмяТэга1С, ПризнакКонцаТэга1С)
			 ИЛИ СтруктураРазбораXML.СтатусТэга1С = 5 И ПустаяСтрока(СтруктураРазбораXML.ИмяОбласти) Тогда
			Текст = СтруктураРазбораXML.ТекстДоТэга1С + СтруктураРазбораXML.ПолноеИмяТэга1С + СтруктураРазбораXML.ТекстПослеТэга1С;
			СброситьСтатусыТэгов1С(СтруктураРазбораXML);
			СтруктураРазбораXML.ТекстДоТэга1С = Текст;
			ДлинаСтрокиТэга1С = 0;
		КонецЕсли;
		
		Если СтруктураРазбораXML.СтатусТэга1С = 1 ИЛИ СтруктураРазбораXML.СтатусТэга1С = 5 Тогда
			СтруктураРазбораXML.СтатусТэга1С = СтруктураРазбораXML.СтатусТэга1С + 1;
		КонецЕсли;
		
		Если СтруктураРазбораXML.СтатусТэга1С = 2 ИЛИ СтруктураРазбораXML.СтатусТэга1С = 6 Тогда
			
			СтруктураРазбораXML.ПолноеИмяТэга1С = СтруктураРазбораXML.ПолноеИмяТэга1С + Символ;
			ДлинаСтрокиТэга1С = ДлинаСтрокиТэга1С + 1;
			
			Если(КодСимвола = 32 ИЛИ (КодСимвола >= 48 И КодСимвола <= 57) ИЛИ (КодСимвола >= 65 И КодСимвола <= 90) ИЛИ КодСимвола = 95 ИЛИ (КодСимвола >= 97 И КодСимвола <= 122) ИЛИ (КодСимвола >= 1040 И КодСимвола <= 1103)) Тогда
				СтруктураРазбораXML.ИмяТэга1С = СтруктураРазбораXML.ИмяТэга1С + Символ;
			ИначеЕсли Символ = "." И СтруктураРазбораXML.ТипТэга1С = 0 И СтруктураРазбораXML.ИмяТэга1С = "Область" Тогда
				СтруктураРазбораXML.ТипТэга1С = 1;
				СтруктураРазбораXML.ИмяТэга1С = "";
			ИначеЕсли Символ = "}" Тогда
				СтруктураРазбораXML.СтатусТэга1С = СтруктураРазбораXML.СтатусТэга1С + 1;
				СтруктураРазбораXML.ИмяТэга1С = СокрЛП(СтруктураРазбораXML.ИмяТэга1С);
			Иначе
				Текст = СтруктураРазбораXML.ТекстДоТэга1С + СтруктураРазбораXML.ПолноеИмяТэга1С + СтруктураРазбораXML.ТекстПослеТэга1С;
				СброситьСтатусыТэгов1С(СтруктураРазбораXML);
				СтруктураРазбораXML.ТекстДоТэга1С = Текст;
				ДлинаСтрокиТэга1С = 0;
			КонецЕсли;
			
		ИначеЕсли СтруктураРазбораXML.СтатусТэга1С = 3 ИЛИ СтруктураРазбораXML.СтатусТэга1С = 7 Тогда
			СтруктураРазбораXML.ТекстПослеТэга1С = СтруктураРазбораXML.ТекстПослеТэга1С + Символ;
		Иначе
			СтруктураРазбораXML.ТекстДоТэга1С = СтруктураРазбораXML.ТекстДоТэга1С + Символ;
		КонецЕсли;
		
	КонецЦикла;
	
	Если СтруктураРазбораXML.СтатусТэга1С = 0 И СтруктураРазбораXML.РазобранныеСтроки.Количество() > 0 Тогда
		СтруктураРазбораXML.СтатусТэга1С = 3;
	КонецЕсли;
	
	Если СтруктураРазбораXML.СтатусТэга1С = 0 Тогда
		СброситьПотокиШаблоннойСтроки(СтруктураРазбораXML);
	Иначе
		ИнициализироватьПотокиШаблоннойСтроки(СтруктураРазбораXML);
	КонецЕсли;
	
	Если СтруктураРазбораXML.СтатусТэга1С = 3 ИЛИ СтруктураРазбораXML.СтатусТэга1С = 7 Тогда
		СформироватьРазобранныеСтроки(СтруктураРазбораXML);
	КонецЕсли;
	
	Если СтруктураРазбораXML.СтатусТэга1С = 0 И СтруктураРазбораXML.РазобранныеСтроки.Количество() = 0 Тогда
		СброситьСтатусыТэгов1С(СтруктураРазбораXML);
	КонецЕсли;
	
КонецПроцедуры

Процедура ВыделитьИзРазделаКолонтитулы(ЧтениеXML, СтруктураДокумента, Раздел)
	
	ТипыКолонтитулов = ТипыКолонтитулов();
	
	Пока ЧтениеXML.Прочитать() Цикл
		
		Если НЕ (ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И (ЧтениеXML.Имя = "w:headerReference" ИЛИ ЧтениеXML.Имя = "w:footerReference")) Тогда
			Продолжить;
		КонецЕсли;
		
		ИмяТэга       = ЧтениеXML.Имя;
		Атрибут_wtype = ЧтениеXML.ПолучитьАтрибут("w:type");
		Атрибут_rid   = ЧтениеXML.ПолучитьАтрибут("r:id");
		
		НайденнаяСтрока = СтруктураДокумента.ТаблицаСвязейКонтента.Найти(Атрибут_rid);
		
		Если НайденнаяСтрока = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		ТипКолонтитула   = ТипыКолонтитулов.Получить(ИмяТэга + "_" + Атрибут_wtype);
		
		СтруктураКолонтитула = ОбластьКолонтитула();
		СтруктураКолонтитула.Имя          = ТипКолонтитула;
		СтруктураКолонтитула.ИмяВнутр     = СтрЗаменить(НайденнаяСтрока.ИмяРесурса, ".xml", "");
		СтруктураКолонтитула.НомерРаздела = Раздел.Номер;
		
		ДобавитьВСтруктуруДокументаКолонтитул(СтруктураДокумента, СтруктураКолонтитула, НайденнаяСтрока.ИмяРесурса);
		
	КонецЦикла;
	
КонецПроцедуры

Функция ОбработатьРазделДокумента(СтруктураДокумента, Раздел)
	
	ТипыКолонтитулов = ТипыКолонтитулов();
	
	ЧтениеXML = ИнициализироватьЧтениеXML(Раздел.Текст);
	ЗаписьXML = ИнициализироватьЗаписьXML("",,,Ложь);
	
	ПропуститьТэг = Ложь;
	Пока ЧтениеXML.Прочитать() Цикл
		
		Если ПропуститьТэг = Истина Тогда
			ПропуститьТэг = Ложь;
			Продолжить;
		КонецЕсли;
		
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И (ЧтениеXML.Имя = "w:document" ИЛИ ЧтениеXML.Имя = "w:body") Тогда
			Продолжить;
		КонецЕсли;
		
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
			Продолжить;
		КонецЕсли;
		
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И (ЧтениеXML.Имя = "w:headerReference" ИЛИ ЧтениеXML.Имя = "w:footerReference") Тогда
			
			ИмяТэга = ЧтениеXML.Имя;
			ЗначениеАтрибута = ЧтениеXML.ПолучитьАтрибут("w:type");
			КлючКолонтитула = ИмяТэга + "_" + ЗначениеАтрибута;
			ТипКолонтитула = ТипыКолонтитулов.Получить(КлючКолонтитула);
			КлючВСтруктуреДокумента = ТипКолонтитула + "_" + Формат(Раздел.Номер, "ЧГ=0");
			КолонтитулВСтруктуре = СтруктураДокумента.Колонтитулы.Получить(КлючВСтруктуреДокумента);
			
			Если КолонтитулВСтруктуре.Текст = "" Тогда
				ПропуститьТэг = Истина;
				Продолжить;
			КонецЕсли;
			
		КонецЕсли;
		
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И (ЧтениеXML.Имя = "w:document" ИЛИ ЧтениеXML.Имя = "w:body") Тогда
			Продолжить;
		КонецЕсли;
		
		ЗаписатьЭлементXML(ЧтениеXML, ЗаписьXML);
		
	КонецЦикла;
	
	ТекстРаздела = ЗаписьXML.Закрыть();
	
	Возврат ТекстРаздела;
	
КонецФункции

#КонецОбласти

#КонецОбласти

#Область РаботаСИзображением

////////////////////////////////////////////////////////////////////////////////
// Функции обработки файлов изображений

// Возвращает ширину, высоту, и тип изображения для файлов GIF, JPG, PNG, BMP, TIFF
Функция ПолучитьАтрибутыИзображения(ДанныеЧтения)
	
	АтрибутыИзображения = Новый Структура;
	
	Если ТипЗнч(ДанныеЧтения) = Тип("Строка") Тогда
		
		Попытка
			ПотокДанных = ФайловыеПотоки.ОткрытьДляЧтения(ДанныеЧтения);
		Исключение
			Возврат АтрибутыИзображения;
		КонецПопытки;
		
	ИначеЕсли ТипЗнч(ДанныеЧтения) = Тип("ДвоичныеДанные") Тогда
		ПотокДанных = ДанныеЧтения
	Иначе
		Возврат АтрибутыИзображения;
	КонецЕсли;
	
	ЧтениеДанных = Новый ЧтениеДанных(ПотокДанных);
	
	Символ1 = ЧтениеДанных.ПрочитатьБайт();
	Символ2 = ЧтениеДанных.ПрочитатьБайт();
	Символ3 = ЧтениеДанных.ПрочитатьБайт();
	
	// MIME syntax -  "type/subtype"
	ТипИзображения = Null;
	
	Ширина  = -1;
	Высота = -1;
	
	Если (Символ(Символ1) = "G" И Символ(Символ2) = "I" И Символ(Символ3) = "F") Тогда // GIF
		
		ЧтениеДанных.Пропустить(3);
		Ширина  = ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 2, Ложь);
		Высота = ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 2 , Ложь);
		ТипИзображения = "image/gif";
		
	ИначеЕсли (Символ1 = 255 И Символ2 = 216) Тогда // JPG
		
		Пока (Символ3 = 255) Цикл 
			
			Маркер = ЧтениеДанных.ПрочитатьБайт();
			Длина = ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 2, Истина);
			
			Если (Маркер = 192 ИЛИ Маркер = 193 ИЛИ Маркер = 194) Тогда
				
				ЧтениеДанных.Пропустить(1);
				Высота = ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 2, Истина);
				Ширина  = ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 2, Истина);
				ТипИзображения = "image/jpeg";
				Прервать;
				
			КонецЕсли;
			
			ЧтениеДанных.Пропустить(Длина - 2);
			Символ3 = ЧтениеДанных.ПрочитатьБайт();
			
		КонецЦикла;
		
	ИначеЕсли  (Символ1 = 137 И Символ2 = 80 И Символ3 = 78) Тогда // PNG
		
		ЧтениеДанных.Пропустить(15);
		Ширина = ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 2 , Истина);
		ЧтениеДанных.Пропустить(2);
		Высота = ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 2, Истина);
		ТипИзображения = "image/png";
		
	ИначеЕсли  (Символ1 = 66 И Символ2 = 77) Тогда // BMP
		
		ЧтениеДанных.Пропустить(15);
		Ширина = ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 2, Ложь);
		ЧтениеДанных.Пропустить(2);
		Высота = ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 2, Ложь);
		ТипИзображения = "image/bmp";
		
	Иначе
		
		Символ4 = ЧтениеДанных.ПрочитатьБайт();
		
		Если((Символ(Символ1) = "M" И Символ(Символ2) = "M" И Символ3 = 0 И Символ4 = 42) ИЛИ (Символ(Символ1) = "I" И Символ(Символ2) = "I" И Символ3 = 42 И Символ4 = 0)) Тогда //TIFF
			
			ПорядокБайтовBigEndian = Символ(Символ1) = "M";
			
			// Image header
			ЗначениеСмещения = 0;
			ЗначениеСмещения = ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 4, ПорядокБайтовBigEndian);
			
			ЧтениеДанных.Пропустить(ЗначениеСмещения - 8);
			Вхождения = ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 2, ПорядокБайтовBigEndian);
			
			Индекс = 1;
			Пока Индекс <= Вхождения Цикл
				
				Тэг = ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 2, ПорядокБайтовBigEndian);
				ТипПоля = ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 2, ПорядокБайтовBigEndian);
				ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 4, ПорядокБайтовBigEndian);
				
				Если (ТипПоля = 3 ИЛИ ТипПоля = 8) Тогда
					
					ЗначениеСмещения = ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 2, ПорядокБайтовBigEndian);
					ЧтениеДанных.Пропустить(2);
					
				Иначе
					
					ЗначениеСмещения = ПрочитатьЗначениеБайтаИзПотока(ЧтениеДанных, 4, ПорядокБайтовBigEndian);
					
				КонецЕсли;
				
				Если (Тэг = 256) Тогда
					
					Ширина = ЗначениеСмещения;
					
				ИначеЕсли (Тэг = 257) Тогда
					
					Высота = ЗначениеСмещения;
					
				КонецЕсли;
				
				Если (Ширина <> -1 И Высота <> -1) Тогда
					
					ТипИзображения = "image/tiff";
					Прервать;
					
				КонецЕсли;
				
				Индекс = Индекс + 1;
				
			КонецЦикла;
			
		КонецЕсли;
		
	КонецЕсли;
	
	ЧтениеДанных.Закрыть();
	
	АтрибутыИзображения.Вставить("ТипИзображения", ТипИзображения);
	АтрибутыИзображения.Вставить("Высота", ?(ТипИзображения = Null, 0, Высота));
	АтрибутыИзображения.Вставить("Ширина", ?(ТипИзображения = Null, 0, Ширина));
	
	Возврат АтрибутыИзображения;
	
КонецФункции

Функция ПрочитатьЗначениеБайтаИзПотока(ПотокВвода, ЧислоБайтов, ПорядокБайтовBigEndian) 
	
	Значение = 0;
	
	ВеличинаСмещения = ?(ПорядокБайтовBigEndian = Истина, (ЧислоБайтов - 1) * 8, 0);
	Количество = ?(ПорядокБайтовBigEndian = Истина, -8, 8); 
	
	Индекс = 0;
	Пока Индекс < ЧислоБайтов Цикл
		
		Значение = ПобитовоеИли_(Значение, ПобитовыйСдвигВлево_(ПотокВвода.ПрочитатьБайт(), ВеличинаСмещения));
		ВеличинаСмещения = ВеличинаСмещения + Количество;
		
		Индекс = Индекс + 1;
		
	КонецЦикла;
	
	Возврат Значение;
	
КонецФункции

Функция ПобитовыйСдвигВлево_(Знач Число, Смещение = 0)
	
	ДвоичноеПредставление = ПолучитьДвоичноеПредставлениеЧисла(Число);
	МассивДвоичногоЧисла  = РазобратьДвоичноеПредставление(ДвоичноеПредставление);
	
	Для Инд = 0 По Смещение - 1 Цикл
		
		Индекс = 1;
		Пока Индекс <= МассивДвоичногоЧисла.ВГраница() - Инд Цикл 
			
			МассивДвоичногоЧисла[Индекс-1] = МассивДвоичногоЧисла[Индекс];
			Индекс = Индекс + 1;
			
		КонецЦикла;
		
		МассивДвоичногоЧисла[МассивДвоичногоЧисла.ВГраница()- Инд] = "0";
		
	КонецЦикла;
	
	
	ДвоичноеПредставлениеМассиваЧисла = ПолучитьДвоичноеПредставлениеМассиваЧисла(МассивДвоичногоЧисла);	
	
	Результат = ЧислоИзДвоичнойСтроки("0b" + ДвоичноеПредставлениеМассиваЧисла);
	
	Возврат Результат;
	
КонецФункции

Функция ПобитовоеИли_(Число1, Число2)
	
	ДвоичноеПредставлениеЧисла1 = ПолучитьДвоичноеПредставлениеЧисла(Число1);
	ДвоичноеПредставлениеЧисла2 = ПолучитьДвоичноеПредставлениеЧисла(Число2);
	
	МассивДвоичногоЧисла1 = РазобратьДвоичноеПредставление(ДвоичноеПредставлениеЧисла1);
	МассивДвоичногоЧисла2 = РазобратьДвоичноеПредставление(ДвоичноеПредставлениеЧисла2);
	
	ДлинаМассива = МассивДвоичногоЧисла1.ВГраница();
	
	Для Инд = 0 По ДлинаМассива Цикл
		
		Если МассивДвоичногоЧисла1[Инд] = "1" ИЛИ МассивДвоичногоЧисла2[Инд] = "1" Тогда
			МассивДвоичногоЧисла1[Инд] = "1";
		КонецЕсли;
		
	КонецЦикла;
	
	ДвоичноеПредставлениеМассиваЧисла = ПолучитьДвоичноеПредставлениеМассиваЧисла(МассивДвоичногоЧисла1);
	
	Результат = ЧислоИзДвоичнойСтроки("0b" + ДвоичноеПредставлениеМассиваЧисла);
	
	Возврат Результат;
	
КонецФункции

Функция ПолучитьДвоичноеПредставлениеЧисла(Значение, Маска = "00000000000000000000000000000000")
	
	Результат = "";
	Шаблон    = "01";
	Основание = СтрДлина(Шаблон);
	
	Пока Значение > 0 Цикл
		
		Остаток    = Значение % Основание;
		Результат1 = Сред(Шаблон, Остаток + 1, 1);
		Значение   = (Значение - Остаток) / Основание;
		Результат  = Результат1 + Результат;
		
	КонецЦикла;
	
	ЧислоНулей = СтрДлина(Маска) - СтрДлина(Результат);
	Для Инд = 1 По ЧислоНулей Цикл 
		Результат = "0" + Результат;
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

Функция ПолучитьДвоичноеПредставлениеМассиваЧисла(МассивДвоичногоЧисла)
	
	Результат = "";
	
	Для Инд = 0 По МассивДвоичногоЧисла.ВГраница() Цикл
		Результат = Результат + МассивДвоичногоЧисла[Инд];
	КонецЦикла;
	
	Возврат Результат
	
КонецФункции

Функция РазобратьДвоичноеПредставление(ДвоичноеПредставление)
	
	МассивДвоичногоЧисла = Новый Массив(СтрДлина(ДвоичноеПредставление));
	
	Для Инд = 0 По МассивДвоичногоЧисла.ВГраница() Цикл
		МассивДвоичногоЧисла[Инд] = Сред(ДвоичноеПредставление, Инд + 1, 1);
	КонецЦикла;
	
	Возврат МассивДвоичногоЧисла;
	
КонецФункции

#КонецОбласти

////////////////////////////////////////////////////////////////////////////////
// Прочие процедуры и функции

Функция СобытиеЖурналаРегистрации()
	
	Возврат НСтр("ru = 'Печать'", ОбщегоНазначения.КодОсновногоЯзыка());
	
КонецФункции

Процедура КопироватьСодержимоеКаталога(Откуда, Куда) Экспорт
	
	КаталогНазначения = Новый Файл(Куда);
	
	Если КаталогНазначения.Существует() Тогда
		Если КаталогНазначения.ЭтоФайл() Тогда
			УдалитьФайлы(КаталогНазначения.ПолноеИмя);
			СоздатьКаталог(Куда);
		КонецЕсли;
	Иначе
		СоздатьКаталог(Куда);
	КонецЕсли;
	
	Файлы = НайтиФайлы(Откуда, ПолучитьМаскуВсеФайлы());
	
	Для Каждого Файл Из Файлы Цикл
		Если Файл.ЭтоКаталог() Тогда
			КопироватьСодержимоеКаталога(Файл.ПолноеИмя, УстановитьРазделительПути(Куда + "\" + Файл.Имя));
		Иначе
			КопироватьФайл(Файл.ПолноеИмя, УстановитьРазделительПути(Куда + "\" + Файл.Имя));
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры

// Параметры:
//   ИмяСобытия  - Строка - имя записываемого события.
//   ПредставлениеУровня  - Строка - представление значений коллекции УровеньЖурналаРегистрации.
//                                     Доступные значения: "Информация", "Ошибка", "Предупреждение", "Примечание".
//   Комментарий - Строка - комментарий события.
//
Процедура ЗаписатьСобытияВЖурналРегистрации(ИмяСобытия, ПредставлениеУровня, Комментарий)
	
	СписокСобытий = Новый СписокЗначений;
	
	СтруктураСобытия = Новый Структура;
	СтруктураСобытия.Вставить("ИмяСобытия", ИмяСобытия);
	СтруктураСобытия.Вставить("ПредставлениеУровня", ПредставлениеУровня);
	СтруктураСобытия.Вставить("Комментарий", Комментарий);
	
	СписокСобытий.Добавить(СтруктураСобытия);
	
	ЖурналРегистрации.ЗаписатьСобытияВЖурналРегистрации(СписокСобытий);
	
КонецПроцедуры

// Определяет расширение файла данных исходя из их его сигнатуры. Файл анализируются
// по первым 8 байтам на отношению к типам docx, doc, odt.
// Для вызова из клиентских и серверных модулей печати форм по макетам офисных документов.
//
// Параметры:
//  ДанныеИлиСтруктура - ДвоичныеДанные
//                     - Структура - файл документа или строка таблицы команд.
//
// Возвращаемое значение:
//  Строка, Неопределено - расширение файла двоичных данных или Неопределено, если не удалось определить расширение. 
//
Функция ОпределитьРасширениеФайлаДанныхПоСигнатуре(ДанныеИлиСтруктура) Экспорт
	
	Если ТипЗнч(ДанныеИлиСтруктура) = Тип("Структура") Тогда
		Попытка
			МакетИДанныеОбъекта = УправлениеПечатью.МакетыИДанныеОбъектовДляПечати(ДанныеИлиСтруктура.МенеджерПечати,
				ДанныеИлиСтруктура.Идентификатор, Новый Массив);
			ДвоичныеДанныеМакета = МакетИДанныеОбъекта.Макеты.ДвоичныеДанныеМакетов.Получить(ДанныеИлиСтруктура.Идентификатор);
		Исключение
			Возврат Неопределено;
		КонецПопытки;
	Иначе
		ДвоичныеДанныеМакета = ДанныеИлиСтруктура;
	КонецЕсли;
	
	Если ДвоичныеДанныеМакета = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	ПотокДанных = ДвоичныеДанныеМакета.ОткрытьПотокДляЧтения();
	ЧтениеДанных = Новый ЧтениеДанных(ПотокДанных);
	
	Символ1 = ЧтениеДанных.ПрочитатьБайт();
	Символ2 = ЧтениеДанных.ПрочитатьБайт();
	Символ3 = ЧтениеДанных.ПрочитатьБайт();
	Символ4 = ЧтениеДанных.ПрочитатьБайт();
	Символ5 = ЧтениеДанных.ПрочитатьБайт();
	Символ6 = ЧтениеДанных.ПрочитатьБайт();
	Символ7 = ЧтениеДанных.ПрочитатьБайт();
	Символ8 = ЧтениеДанных.ПрочитатьБайт();
	
	ПотокДанных.Закрыть();
	
	Если Символ1 = 208 И Символ2 = 207 И Символ3 = 17 И Символ4 = 224 И Символ5 = 161 И Символ6 = 177 И Символ7 = 26 И Символ8 = 225 Тогда
		Возврат "doc";
	ИначеЕсли Символ1 = 80 И Символ2 = 75 И Символ3 = 3 И Символ4 = 4 И Символ5 = 20
			  ИЛИ Символ1 = 80 И Символ2 = 75 И Символ3 = 3 И Символ4 = 4 И Символ5 = 10 Тогда
			  	
		ИмяВременногоФайла = ПолучитьИмяВременногоФайла("docx");
	
		ДвоичныеДанныеМакета.Записать(ИмяВременногоФайла);
		Попытка
			Архиватор = Новый ЧтениеZipФайла(ИмяВременногоФайла);
		Исключение
			УдалитьФайлы(ИмяВременногоФайла);
			ЗаписатьСобытияВЖурналРегистрации(СобытиеЖурналаРегистрации(), "Ошибка", ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
			ВызватьИсключение(НСтр("ru = 'Не удалось открыть файл шаблона по причине:'") + Символы.ПС 
				+ ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
		КонецПопытки;
		
		Если Архиватор.Элементы.Найти("document.xml") = Неопределено Тогда
			Расширение = "odt";
		Иначе
			Расширение = "docx";
		КонецЕсли;
		Архиватор.Закрыть();
		УдалитьФайлы(ИмяВременногоФайла);
		
		Возврат Расширение;
	Иначе
		Возврат Неопределено;
	КонецЕсли;
	
КонецФункции

Функция УстановитьРазделительПути(Знач Путь)
	Возврат СтрСоединить(СтрРазделить(Путь, "\/", Истина), ПолучитьРазделительПути());
КонецФункции

#КонецОбласти

#КонецОбласти
